From bed7d277343ec23747a521c21dcade48f8cef7e6 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Thu, 21 Nov 2024 15:58:00 +0200 Subject: [PATCH 01/47] add resource permission checks --- .../dataall/core/environment/api/resolvers.py | 5 +- .../services/organization_service.py | 7 ++ .../core/stacks/services/stack_service.py | 9 +- .../dataall/core/vpc/services/vpc_service.py | 12 +- .../modules/datapipelines/api/resolvers.py | 1 + .../modules/datasets_base/api/resolvers.py | 3 +- .../dataall/modules/mlstudio/api/resolvers.py | 1 + .../modules/notebooks/api/resolvers.py | 1 + .../api/datasets/resolvers.py | 2 +- .../s3_datasets/api/dataset/resolvers.py | 3 +- .../s3_datasets/services/dataset_service.py | 2 + tests/test_tenant_unauthorized.py | 111 +++++++++++++++++- 12 files changed, 146 insertions(+), 11 deletions(-) diff --git a/backend/dataall/core/environment/api/resolvers.py b/backend/dataall/core/environment/api/resolvers.py index 2f3301c74..01a3c1bde 100644 --- a/backend/dataall/core/environment/api/resolvers.py +++ b/backend/dataall/core/environment/api/resolvers.py @@ -14,7 +14,6 @@ from dataall.core.organizations.api.resolvers import Context, exceptions, get_organization_simplified - log = logging.getLogger() @@ -223,6 +222,7 @@ def generate_environment_access_token(context, source, environmentUri: str = Non def get_environment_stack(context: Context, source: Environment, **kwargs): return StackService.resolve_parent_obj_stack( targetUri=source.environmentUri, + targetType='environment', environmentUri=source.environmentUri, ) @@ -275,8 +275,7 @@ def resolve_environment(context, source, **kwargs): """Resolves the environment for a environmental resource""" if not source: return None - with context.engine.scoped_session() as session: - return EnvironmentService.get_environment_by_uri(session, source.environmentUri) + return EnvironmentService.find_environment_by_uri(uri=source.environmentUri) def resolve_parameters(context, source: Environment, **kwargs): diff --git a/backend/dataall/core/organizations/services/organization_service.py b/backend/dataall/core/organizations/services/organization_service.py index 696ae0881..798480dc0 100644 --- a/backend/dataall/core/organizations/services/organization_service.py +++ b/backend/dataall/core/organizations/services/organization_service.py @@ -305,6 +305,13 @@ def resolve_organization_by_env(uri): context = get_context() with context.db_engine.scoped_session() as session: env = EnvironmentRepository.get_environment_by_uri(session, uri) + ResourcePolicyService.check_user_resource_permission( + session=session, + username=get_context().username, + groups=get_context().groups, + resource_uri=env.organizationUri, + permission_name=GET_ORGANIZATION, + ) return OrganizationRepository.find_organization_by_uri(session, env.organizationUri) @staticmethod diff --git a/backend/dataall/core/stacks/services/stack_service.py b/backend/dataall/core/stacks/services/stack_service.py index d02d9ba48..657b3f51a 100644 --- a/backend/dataall/core/stacks/services/stack_service.py +++ b/backend/dataall/core/stacks/services/stack_service.py @@ -65,10 +65,17 @@ def map_target_type_to_log_config_path(**kwargs): class StackService: @staticmethod - def resolve_parent_obj_stack(targetUri: str, environmentUri: str): + def resolve_parent_obj_stack(targetUri: str, targetType: str, environmentUri: str): context = get_context() with context.db_engine.scoped_session() as session: env: Environment = EnvironmentRepository.get_environment_by_uri(session, environmentUri) + ResourcePolicyService.check_user_resource_permission( + session=session, + username=context.username, + groups=context.groups, + resource_uri=targetUri, + permission_name=TargetType.get_resource_read_permission_name(targetType), + ) stack: Stack = StackRepository.find_stack_by_target_uri(session, target_uri=targetUri) if not stack: stack = Stack( diff --git a/backend/dataall/core/vpc/services/vpc_service.py b/backend/dataall/core/vpc/services/vpc_service.py index 48c9c726c..87c9bd2ed 100644 --- a/backend/dataall/core/vpc/services/vpc_service.py +++ b/backend/dataall/core/vpc/services/vpc_service.py @@ -7,7 +7,7 @@ from dataall.core.permissions.services.tenant_policy_service import TenantPolicyService from dataall.core.vpc.db.vpc_repositories import VpcRepository from dataall.core.vpc.db.vpc_models import Vpc -from dataall.core.permissions.services.network_permissions import NETWORK_ALL, DELETE_NETWORK +from dataall.core.permissions.services.network_permissions import NETWORK_ALL, DELETE_NETWORK, GET_NETWORK from dataall.core.permissions.services.environment_permissions import CREATE_NETWORK from dataall.core.permissions.services.tenant_permissions import MANAGE_ENVIRONMENTS @@ -90,4 +90,12 @@ def delete_network(uri): @staticmethod def get_environment_networks(environment_uri): with _session() as session: - return VpcRepository.get_environment_networks(session=session, environment_uri=environment_uri) + vpc = VpcRepository.get_environment_networks(session=session, environment_uri=environment_uri) + ResourcePolicyService.check_user_resource_permission( + session=session, + username=get_context().username, + groups=get_context().groups, + resource_uri=vpc.vpcUri, + permission_name=GET_NETWORK, + ) + return vpc diff --git a/backend/dataall/modules/datapipelines/api/resolvers.py b/backend/dataall/modules/datapipelines/api/resolvers.py index 3c2bde886..47e676816 100644 --- a/backend/dataall/modules/datapipelines/api/resolvers.py +++ b/backend/dataall/modules/datapipelines/api/resolvers.py @@ -105,5 +105,6 @@ def resolve_stack(context, source: DataPipeline, **kwargs): return None return StackService.resolve_parent_obj_stack( targetUri=source.DataPipelineUri, + targetType='pipeline', environmentUri=source.environmentUri, ) diff --git a/backend/dataall/modules/datasets_base/api/resolvers.py b/backend/dataall/modules/datasets_base/api/resolvers.py index 73f6539c7..48e424ad1 100644 --- a/backend/dataall/modules/datasets_base/api/resolvers.py +++ b/backend/dataall/modules/datasets_base/api/resolvers.py @@ -59,7 +59,7 @@ def get_dataset_environment(context, source: DatasetBase, **kwargs): if not source: return None with context.engine.scoped_session() as session: - return EnvironmentService.get_environment_by_uri(session, source.environmentUri) + return EnvironmentService.find_environment_by_uri(session, uri=source.environmentUri) def get_dataset_owners_group(context, source: DatasetBase, **kwargs): @@ -79,5 +79,6 @@ def resolve_dataset_stack(context: Context, source: DatasetBase, **kwargs): return None return StackService.resolve_parent_obj_stack( targetUri=source.datasetUri, + targetType='dataset', environmentUri=source.environmentUri, ) diff --git a/backend/dataall/modules/mlstudio/api/resolvers.py b/backend/dataall/modules/mlstudio/api/resolvers.py index e38d72ae6..6d4e07f8b 100644 --- a/backend/dataall/modules/mlstudio/api/resolvers.py +++ b/backend/dataall/modules/mlstudio/api/resolvers.py @@ -122,6 +122,7 @@ def resolve_sagemaker_studio_user_stack(context: Context, source: SagemakerStudi return None return StackService.resolve_parent_obj_stack( targetUri=source.sagemakerStudioUserUri, + targetType='mlstudio', environmentUri=source.environmentUri, ) diff --git a/backend/dataall/modules/notebooks/api/resolvers.py b/backend/dataall/modules/notebooks/api/resolvers.py index de6235305..e7e111fc3 100644 --- a/backend/dataall/modules/notebooks/api/resolvers.py +++ b/backend/dataall/modules/notebooks/api/resolvers.py @@ -90,6 +90,7 @@ def resolve_notebook_stack(context: Context, source: SagemakerNotebook, **kwargs return None return StackService.resolve_parent_obj_stack( targetUri=source.notebookUri, + targetType='notebook', environmentUri=source.environmentUri, ) diff --git a/backend/dataall/modules/redshift_datasets/api/datasets/resolvers.py b/backend/dataall/modules/redshift_datasets/api/datasets/resolvers.py index e95480351..06683c2c0 100644 --- a/backend/dataall/modules/redshift_datasets/api/datasets/resolvers.py +++ b/backend/dataall/modules/redshift_datasets/api/datasets/resolvers.py @@ -88,7 +88,7 @@ def resolve_dataset_environment( if not source: return None with context.engine.scoped_session() as session: - return EnvironmentService.get_environment_by_uri(session, source.environmentUri) + return EnvironmentService.find_environment_by_uri(session, uri=source.environmentUri) def resolve_dataset_owners_group( diff --git a/backend/dataall/modules/s3_datasets/api/dataset/resolvers.py b/backend/dataall/modules/s3_datasets/api/dataset/resolvers.py index 11a183f2b..7808cb253 100644 --- a/backend/dataall/modules/s3_datasets/api/dataset/resolvers.py +++ b/backend/dataall/modules/s3_datasets/api/dataset/resolvers.py @@ -86,7 +86,7 @@ def get_dataset_environment(context, source: S3Dataset, **kwargs): if not source: return None with context.engine.scoped_session() as session: - return EnvironmentService.get_environment_by_uri(session, source.environmentUri) + return EnvironmentService.find_environment_by_uri(session, uri=source.environmentUri) def get_dataset_owners_group(context, source: S3Dataset, **kwargs): @@ -133,6 +133,7 @@ def resolve_dataset_stack(context: Context, source: S3Dataset, **kwargs): return None return StackService.resolve_parent_obj_stack( targetUri=source.datasetUri, + targetType='dataset', environmentUri=source.environmentUri, ) diff --git a/backend/dataall/modules/s3_datasets/services/dataset_service.py b/backend/dataall/modules/s3_datasets/services/dataset_service.py index a279c97db..252a709ef 100644 --- a/backend/dataall/modules/s3_datasets/services/dataset_service.py +++ b/backend/dataall/modules/s3_datasets/services/dataset_service.py @@ -38,6 +38,7 @@ DATASET_ALL, DATASET_READ, IMPORT_DATASET, + GET_DATASET, DATASET_TABLE_ALL, ) from dataall.modules.datasets_base.services.dataset_list_permissions import LIST_ENVIRONMENT_DATASETS @@ -234,6 +235,7 @@ def import_dataset(uri, admin_group, data): return DatasetService.create_dataset(uri=uri, admin_group=admin_group, data=data) @staticmethod + @ResourcePolicyService.has_resource_permission(GET_DATASET) def get_dataset(uri): context = get_context() with context.db_engine.scoped_session() as session: diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index f87b5dde7..a26766852 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -1,12 +1,18 @@ -from unittest.mock import MagicMock, patch +import logging +from unittest.mock import MagicMock, patch, ANY import pytest from assertpy import assert_that from dataall.base.api import bootstrap from dataall.base.loader import load_modules, ImportMode from dataall.base.context import RequestContext -from dataall.base.db.exceptions import TenantUnauthorized +from dataall.base.db.exceptions import TenantUnauthorized, ResourceUnauthorized import inspect +from dataall.core.permissions.services.environment_permissions import GET_ENVIRONMENT +from dataall.core.permissions.services.network_permissions import GET_NETWORK +from dataall.core.permissions.services.organization_permissions import GET_ORGANIZATION +from dataall.modules.datapipelines.services.datapipelines_permissions import GET_PIPELINE +from dataall.modules.s3_datasets.services.dataset_permissions import GET_DATASET, GET_DATASET_TABLE load_modules(modes={ImportMode.API}) @@ -86,3 +92,104 @@ def test_unauthorized_tenant_permissions( iargs = {arg: MagicMock() for arg in inspect.signature(field.resolver).parameters.keys()} # Assert Unauthorized exception is raised assert_that(field.resolver).raises(TenantUnauthorized).when_called_with(**iargs).contains('UnauthorizedOperation') + + +IGNORE_NESTED_RESOLVERS = [ + 'AttachedMetadataForm_entityName', + 'AttachedMetadataForm_fields', + 'AttachedMetadataForm_metadataForm', + 'AttachedMetadataFormField_field', + 'AttachedMetadataFormField_hasTenantPermissions', + 'Category_associations', + 'Category_categories', + 'Category_children', + 'Category_stats', + 'Category_terms', + 'Dashboard_terms', + 'Dashboard_upvotes', + 'Dashboard_userRoleForDashboard', + 'DataPipeline_cloneUrlHttp', + 'DataPipeline_developmentEnvironments', + 'DataPipeline_userRoleForPipeline', + 'Dataset_locations', + 'Dataset_owners', + 'Dataset_statistics', + 'Dataset_stewards', + 'Dataset_tables', + 'Dataset_terms', + 'Dataset_userRoleForDataset', + 'DatasetBase_owners', + 'DatasetBase_stewards', + 'DatasetBase_userRoleForDataset', + 'DatasetProfilingRun_results', + 'DatasetProfilingRun_status', + 'DatasetStorageLocation_terms', + 'DatasetTable_columns', + 'DatasetTable_terms', + 'DatasetTableColumn_terms', + 'Environment_organization', + 'Environment_parameters', + 'Environment_userRoleInEnvironment', + 'EnvironmentSimplified_organization', +] + +EXPECTED_PERMS = { + 'ConsumptionRole_managedPolicies': GET_ENVIRONMENT, + 'Dashboard_environment': GET_ENVIRONMENT, + 'DataPipeline_environment': GET_ENVIRONMENT, + 'DataPipeline_organization': GET_ORGANIZATION, + 'DataPipeline_stack': GET_PIPELINE, + 'Dataset_environment': GET_ENVIRONMENT, + 'Dataset_stack': GET_DATASET, + 'DatasetBase_environment': GET_ENVIRONMENT, + 'DatasetBase_stack': GET_DATASET, + 'DatasetProfilingRun_dataset': GET_DATASET, + 'DatasetTable_dataset': GET_DATASET, + 'DatasetTable_GlueTableProperties': GET_DATASET_TABLE, + 'Environment_networks': GET_NETWORK, + 'Environment_stack': GET_ENVIRONMENT, + 'EnvironmentSimplified_networks': GET_NETWORK, +} + + +@patch('dataall.base.aws.sts.SessionHelper.remote_session') +@patch('dataall.core.permissions.services.resource_policy_service.ResourcePolicyService.check_user_resource_permission') +@patch('dataall.base.context._request_storage') +@pytest.mark.parametrize( + 'field', + [ + pytest.param(field, id=f'{_type.name}_{field.name}') + for _type, field in ALL_RESOLVERS + if _type.name not in ['Query', 'Mutation'] # filter out top-level queries (don't print skip) + ], +) +def test_unauthorized_resource_permissions( + mock_local, + mock_check, + mock_session, + field, + request, +): + msg = ( + f'{request.node.callspec.id} -> {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' + ) + logging.info(msg) + if request.node.callspec.id in IGNORE_NESTED_RESOLVERS: + pytest.skip(msg) + + assert_that(field.resolver).is_not_none() + username = 'ausername' + groups = ['agroup'] + mock_local.context = RequestContext(MagicMock(), username, groups, 'auserid') + mock_check.side_effect = ResourceUnauthorized(groups, 'test_action', 'test_uri') + iargs = {arg: MagicMock() for arg in inspect.signature(field.resolver).parameters.keys()} + assert_that(field.resolver).described_as( + f'resolver code: {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' + ).raises(ResourceUnauthorized).when_called_with(**iargs).contains('UnauthorizedOperation', 'test_action') + mock_check.assert_called_once_with( + session=ANY, + resource_uri=ANY, + username=username, + groups=groups, + permission_name=EXPECTED_PERMS.get(request.node.callspec.id, 'FOO_TEST_PERM'), + ) From 15b19b86fb6b9eabe40feb83eaccd4a38d5b6fc2 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Thu, 21 Nov 2024 16:45:29 +0200 Subject: [PATCH 02/47] force enable all modules --- tests/conftest.py | 9 ++++++--- tests/test_tenant_unauthorized.py | 10 ++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 99a17b4c4..39c7e7664 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,20 +1,23 @@ import os from dataclasses import dataclass +from glob import glob from unittest.mock import MagicMock import pytest from starlette.testclient import TestClient +from dataall.base.config import config from dataall.base.db import get_engine, create_schema_and_tables, Engine from dataall.base.loader import load_modules, ImportMode, list_loaded_modules -from glob import glob - from dataall.core.groups.db.group_models import Group from dataall.core.permissions.services.permission_service import PermissionService -from dataall.core.permissions.services.tenant_policy_service import TenantPolicyService from dataall.core.permissions.services.tenant_permissions import TENANT_ALL +from dataall.core.permissions.services.tenant_policy_service import TenantPolicyService from tests.client import create_app, ClientWrapper +for module in config.get_property('modules'): + config.set_property(f'modules.{module}.active', True) + load_modules(modes=ImportMode.all()) ENVNAME = os.environ.get('envname', 'pytest') diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index a26766852..d9acce342 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -1,21 +1,19 @@ +import inspect import logging from unittest.mock import MagicMock, patch, ANY + import pytest from assertpy import assert_that + from dataall.base.api import bootstrap -from dataall.base.loader import load_modules, ImportMode from dataall.base.context import RequestContext from dataall.base.db.exceptions import TenantUnauthorized, ResourceUnauthorized -import inspect - from dataall.core.permissions.services.environment_permissions import GET_ENVIRONMENT from dataall.core.permissions.services.network_permissions import GET_NETWORK from dataall.core.permissions.services.organization_permissions import GET_ORGANIZATION from dataall.modules.datapipelines.services.datapipelines_permissions import GET_PIPELINE from dataall.modules.s3_datasets.services.dataset_permissions import GET_DATASET, GET_DATASET_TABLE -load_modules(modes={ImportMode.API}) - OPT_OUT_MUTATIONS = { 'Mutation.updateGroupTenantPermissions': 'admin action. No need for tenant permission check', 'Mutation.updateSSMParameter': 'admin action. No need for tenant permission check', @@ -173,9 +171,9 @@ def test_unauthorized_resource_permissions( msg = ( f'{request.node.callspec.id} -> {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' ) - logging.info(msg) if request.node.callspec.id in IGNORE_NESTED_RESOLVERS: pytest.skip(msg) + logging.info(msg) assert_that(field.resolver).is_not_none() username = 'ausername' From 646c7ebd20c786f3244b1cbd66e92bd63403b08f Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Thu, 21 Nov 2024 16:48:23 +0200 Subject: [PATCH 03/47] test_id --- tests/test_tenant_unauthorized.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index d9acce342..ad834180e 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -168,10 +168,9 @@ def test_unauthorized_resource_permissions( field, request, ): - msg = ( - f'{request.node.callspec.id} -> {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' - ) - if request.node.callspec.id in IGNORE_NESTED_RESOLVERS: + test_id = request.node.callspec.id + msg = f'{test_id} -> {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' + if test_id in IGNORE_NESTED_RESOLVERS: pytest.skip(msg) logging.info(msg) @@ -189,5 +188,5 @@ def test_unauthorized_resource_permissions( resource_uri=ANY, username=username, groups=groups, - permission_name=EXPECTED_PERMS.get(request.node.callspec.id, 'FOO_TEST_PERM'), + permission_name=EXPECTED_PERMS.get(test_id, 'FOO_TEST_PERM'), ) From cf5a0bef6663196cb8f86f800dbcb9705ce520ed Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Thu, 21 Nov 2024 17:34:11 +0200 Subject: [PATCH 04/47] DRY --- tests/test_tenant_unauthorized.py | 257 +++++++++++++++++++----------- 1 file changed, 167 insertions(+), 90 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index ad834180e..60af508e9 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -1,5 +1,6 @@ import inspect import logging +from enum import Enum from unittest.mock import MagicMock, patch, ANY import pytest @@ -14,35 +15,53 @@ from dataall.modules.datapipelines.services.datapipelines_permissions import GET_PIPELINE from dataall.modules.s3_datasets.services.dataset_permissions import GET_DATASET, GET_DATASET_TABLE + +def resolver_id(type_name, field_name): + return f'{type_name}_{field_name}' + + +class IgnoreReason(Enum): + ADMIN = 'admin action. No need for tenant permission check' + SUPPORT = 'tenant permissions do not apply to support notifications' + FEED = 'tenant permissions do not apply to support feed messages' + VOTES = 'tenant permissions do not apply to support votes' + BACKPORT = 'outside of this PR to be able to backport to v2.6.2' + + +def get_resid(type_name: str, field_name: str) -> str: + return f'{type_name}_{field_name}' + + OPT_OUT_MUTATIONS = { - 'Mutation.updateGroupTenantPermissions': 'admin action. No need for tenant permission check', - 'Mutation.updateSSMParameter': 'admin action. No need for tenant permission check', - 'Mutation.createQuicksightDataSourceSet': 'admin action. No need for tenant permission check', - 'Mutation.startMaintenanceWindow': 'admin action. No need for tenant permission check', - 'Mutation.stopMaintenanceWindow': 'admin action. No need for tenant permission check', - 'Mutation.startReindexCatalog': 'admin action. No need for tenant permission check', - 'Mutation.markNotificationAsRead': 'tenant permissions do not apply to support notifications', - 'Mutation.deleteNotification': 'tenant permissions do not apply to support notifications', - 'Mutation.postFeedMessage': 'tenant permissions do not apply to support feed messages', - 'Mutation.upVote': 'tenant permissions do not apply to support votes', - 'Mutation.createAttachedMetadataForm': 'outside of this PR to be able to backport to v2.6.2', - 'Mutation.deleteAttachedMetadataForm': 'outside of this PR to be able to backport to v2.6.2', - 'Mutation.createRedshiftConnection': 'outside of this PR to be able to backport to v2.6.2', - 'Mutation.deleteRedshiftConnection': 'outside of this PR to be able to backport to v2.6.2', - 'Mutation.addConnectionGroupPermission': 'outside of this PR to be able to backport to v2.6.2', - 'Mutation.deleteConnectionGroupPermission': 'outside of this PR to be able to backport to v2.6.2', + # Admin actions + get_resid('Mutation', 'updateGroupTenantPermissions'): IgnoreReason.ADMIN.value, + get_resid('Mutation', 'updateSSMParameter'): IgnoreReason.ADMIN.value, + get_resid('Mutation', 'createQuicksightDataSourceSet'): IgnoreReason.ADMIN.value, + get_resid('Mutation', 'startMaintenanceWindow'): IgnoreReason.ADMIN.value, + get_resid('Mutation', 'stopMaintenanceWindow'): IgnoreReason.ADMIN.value, + get_resid('Mutation', 'startReindexCatalog'): IgnoreReason.ADMIN.value, + + # Support-related actions + get_resid('Mutation', 'markNotificationAsRead'): IgnoreReason.SUPPORT.value, + get_resid('Mutation', 'deleteNotification'): IgnoreReason.SUPPORT.value, + get_resid('Mutation', 'postFeedMessage'): IgnoreReason.FEED.value, + get_resid('Mutation', 'upVote'): IgnoreReason.VOTES.value, + + # Backport-related actions + get_resid('Mutation', 'createAttachedMetadataForm'): IgnoreReason.BACKPORT.value, + get_resid('Mutation', 'deleteAttachedMetadataForm'): IgnoreReason.BACKPORT.value, + get_resid('Mutation', 'createRedshiftConnection'): IgnoreReason.BACKPORT.value, + get_resid('Mutation', 'deleteRedshiftConnection'): IgnoreReason.BACKPORT.value, + get_resid('Mutation', 'addConnectionGroupPermission'): IgnoreReason.BACKPORT.value, + get_resid('Mutation', 'deleteConnectionGroupPermission'): IgnoreReason.BACKPORT.value, } OPT_IN_QUERIES = [ - 'Query.generateEnvironmentAccessToken', - 'Query.getEnvironmentAssumeRoleUrl', - 'Query.getSagemakerStudioUserPresignedUrl', - 'Query.getSagemakerNotebookPresignedUrl', - 'Query.getDatasetAssumeRoleUrl', - 'Query.getDatasetPresignedUrl', - 'Query.getAuthorSession', - 'Query.getDatasetSharedAssumeRoleUrl', - 'Query.runAthenaSqlQuery', + get_resid('Query', 'generateEnvironmentAccessToken'), + get_resid('Query', 'getEnvironmentAssumeRoleUrl'), + get_resid('Query', 'getSagemakerStudioUserPresignedUrl'), + get_resid('Query', 'getSagemakerNotebookPresignedUrl'), + get_resid('Query', 'getDatasetAssumeRoleUrl'), ] ALL_RESOLVERS = {(_type, field) for _type in bootstrap().types for field in _type.fields if field.resolver} @@ -69,19 +88,27 @@ def mock_input_validation(mocker): @pytest.mark.parametrize( '_type,field', [ - pytest.param(_type, field, id=f'{_type.name}.{field.name}') + pytest.param(_type, field, id=get_resid(_type.name, field.name)) for _type, field in ALL_RESOLVERS if _type.name in ['Query', 'Mutation'] ], ) @patch('dataall.base.context._request_storage') def test_unauthorized_tenant_permissions( - mock_local, _type, field, mock_input_validation, db, userNoTenantPermissions, groupNoTenantPermissions + mock_local, + _type, + field, + request, + mock_input_validation, + db, + userNoTenantPermissions, + groupNoTenantPermissions, ): - if _type.name == 'Mutation' and f'{_type.name}.{field.name}' in OPT_OUT_MUTATIONS.keys(): - pytest.skip(f'Skipping test for {field.name}: {OPT_OUT_MUTATIONS[f"{_type.name}.{field.name}"]}') - if _type.name == 'Query' and f'{_type.name}.{field.name}' not in OPT_IN_QUERIES: - pytest.skip(f'Skipping test for {field.name}: This Query does not require a tenant permission check.') + res_id = request.node.callspec.id + if _type.name == 'Mutation' and res_id in OPT_OUT_MUTATIONS.keys(): + pytest.skip(f'Skipping test for {res_id}: {OPT_OUT_MUTATIONS[res_id]}') + if _type.name == 'Query' and res_id not in OPT_IN_QUERIES: + pytest.skip(f'Skipping test for {res_id}: This Query does not require a tenant permission check.') assert_that(field.resolver).is_not_none() mock_local.context = RequestContext( db, userNoTenantPermissions.username, [groupNoTenantPermissions.groupUri], userNoTenantPermissions @@ -92,61 +119,110 @@ def test_unauthorized_tenant_permissions( assert_that(field.resolver).raises(TenantUnauthorized).when_called_with(**iargs).contains('UnauthorizedOperation') -IGNORE_NESTED_RESOLVERS = [ - 'AttachedMetadataForm_entityName', - 'AttachedMetadataForm_fields', - 'AttachedMetadataForm_metadataForm', - 'AttachedMetadataFormField_field', - 'AttachedMetadataFormField_hasTenantPermissions', - 'Category_associations', - 'Category_categories', - 'Category_children', - 'Category_stats', - 'Category_terms', - 'Dashboard_terms', - 'Dashboard_upvotes', - 'Dashboard_userRoleForDashboard', - 'DataPipeline_cloneUrlHttp', - 'DataPipeline_developmentEnvironments', - 'DataPipeline_userRoleForPipeline', - 'Dataset_locations', - 'Dataset_owners', - 'Dataset_statistics', - 'Dataset_stewards', - 'Dataset_tables', - 'Dataset_terms', - 'Dataset_userRoleForDataset', - 'DatasetBase_owners', - 'DatasetBase_stewards', - 'DatasetBase_userRoleForDataset', - 'DatasetProfilingRun_results', - 'DatasetProfilingRun_status', - 'DatasetStorageLocation_terms', - 'DatasetTable_columns', - 'DatasetTable_terms', - 'DatasetTableColumn_terms', - 'Environment_organization', - 'Environment_parameters', - 'Environment_userRoleInEnvironment', - 'EnvironmentSimplified_organization', -] +SKIP_MARK = 'SKIP_MARK' + +NESTED_RESOLVERS_EXPECTED_PERMS = { + # AttachedMetadataForm related + get_resid('AttachedMetadataFormField', 'field'): SKIP_MARK, + get_resid('AttachedMetadataFormField', 'hasTenantPermissions'): SKIP_MARK, + get_resid('AttachedMetadataForm', 'entityName'): SKIP_MARK, + get_resid('AttachedMetadataForm', 'fields'): SKIP_MARK, + get_resid('AttachedMetadataForm', 'metadataForm'): SKIP_MARK, + + # Category related + get_resid('Category', 'associations'): SKIP_MARK, + get_resid('Category', 'categories'): SKIP_MARK, + get_resid('Category', 'children'): SKIP_MARK, + get_resid('Category', 'stats'): SKIP_MARK, + get_resid('Category', 'terms'): SKIP_MARK, + + # ConsumptionRole related + get_resid('ConsumptionRole', 'managedPolicies'): GET_ENVIRONMENT, + + # Dashboard related + get_resid('Dashboard', 'environment'): GET_ENVIRONMENT, + get_resid('Dashboard', 'terms'): SKIP_MARK, + get_resid('Dashboard', 'upvotes'): SKIP_MARK, + get_resid('Dashboard', 'userRoleForDashboard'): SKIP_MARK, + + # DataPipeline related + get_resid('DataPipeline', 'cloneUrlHttp'): SKIP_MARK, + get_resid('DataPipeline', 'developmentEnvironments'): SKIP_MARK, + get_resid('DataPipeline', 'environment'): GET_ENVIRONMENT, + get_resid('DataPipeline', 'organization'): GET_ORGANIZATION, + get_resid('DataPipeline', 'stack'): GET_PIPELINE, + get_resid('DataPipeline', 'userRoleForPipeline'): SKIP_MARK, + + # Dataset related + get_resid('DatasetBase', 'environment'): GET_ENVIRONMENT, + get_resid('DatasetBase', 'owners'): SKIP_MARK, + get_resid('DatasetBase', 'stack'): GET_DATASET, + get_resid('DatasetBase', 'stewards'): SKIP_MARK, + get_resid('DatasetBase', 'userRoleForDataset'): SKIP_MARK, + + # Dataset Profiling related + get_resid('DatasetProfilingRun', 'dataset'): GET_DATASET, + get_resid('DatasetProfilingRun', 'results'): SKIP_MARK, + get_resid('DatasetProfilingRun', 'status'): SKIP_MARK, + + # Dataset Storage and Table related + get_resid('DatasetStorageLocation', 'terms'): SKIP_MARK, + get_resid('DatasetTableColumn', 'terms'): SKIP_MARK, + get_resid('DatasetTable', 'GlueTableProperties'): GET_DATASET_TABLE, + get_resid('DatasetTable', 'columns'): SKIP_MARK, + get_resid('DatasetTable', 'dataset'): GET_DATASET, + get_resid('DatasetTable', 'terms'): SKIP_MARK, + + # Dataset specific + get_resid('Dataset', 'environment'): GET_ENVIRONMENT, + get_resid('Dataset', 'locations'): SKIP_MARK, + get_resid('Dataset', 'owners'): SKIP_MARK, + get_resid('Dataset', 'stack'): GET_DATASET, + get_resid('Dataset', 'statistics'): SKIP_MARK, + get_resid('Dataset', 'stewards'): SKIP_MARK, + get_resid('Dataset', 'tables'): SKIP_MARK, + get_resid('Dataset', 'terms'): SKIP_MARK, + get_resid('Dataset', 'userRoleForDataset'): SKIP_MARK, + + # Environment related + get_resid('EnvironmentSimplified', 'networks'): GET_NETWORK, + get_resid('EnvironmentSimplified', 'organization'): SKIP_MARK, + get_resid('Environment', 'networks'): GET_NETWORK, + get_resid('Environment', 'organization'): SKIP_MARK, + get_resid('Environment', 'parameters'): SKIP_MARK, + get_resid('Environment', 'stack'): GET_ENVIRONMENT, + get_resid('Environment', 'userRoleInEnvironment'): SKIP_MARK, + + # Feed and Glossary related + get_resid('Feed', 'messages'): SKIP_MARK, + get_resid('GlossaryTermLink', 'target'): SKIP_MARK, + get_resid('GlossaryTermLink', 'term'): SKIP_MARK, + get_resid('Glossary', 'associations'): SKIP_MARK, + get_resid('Glossary', 'categories'): SKIP_MARK, + get_resid('Glossary', 'children'): SKIP_MARK, + get_resid('Glossary', 'stats'): SKIP_MARK, + get_resid('Glossary', 'tree'): SKIP_MARK, + get_resid('Glossary', 'userRoleForGlossary'): SKIP_MARK, + + # Group and Metadata related + get_resid('Group', 'environmentPermissions'): SKIP_MARK, + get_resid('Group', 'tenantPermissions'): SKIP_MARK, + get_resid('MetadataFormField', 'glossaryNodeName'): SKIP_MARK, + get_resid('MetadataFormSearchResult', 'hasTenantPermissions'): SKIP_MARK, + get_resid('MetadataForm', 'fields'): SKIP_MARK, + get_resid('MetadataForm', 'homeEntityName'): SKIP_MARK, + get_resid('MetadataForm', 'userRole'): SKIP_MARK, + + # Omics related + get_resid('OmicsRun', 'environment'): GET_ENVIRONMENT, + get_resid('OmicsRun', 'organization'): GET_ORGANIZATION, + get_resid('OmicsRun', 'status'): SKIP_MARK, + get_resid('OmicsRun', 'workflow'): SKIP_MARK, -EXPECTED_PERMS = { - 'ConsumptionRole_managedPolicies': GET_ENVIRONMENT, - 'Dashboard_environment': GET_ENVIRONMENT, - 'DataPipeline_environment': GET_ENVIRONMENT, - 'DataPipeline_organization': GET_ORGANIZATION, - 'DataPipeline_stack': GET_PIPELINE, - 'Dataset_environment': GET_ENVIRONMENT, - 'Dataset_stack': GET_DATASET, - 'DatasetBase_environment': GET_ENVIRONMENT, - 'DatasetBase_stack': GET_DATASET, - 'DatasetProfilingRun_dataset': GET_DATASET, - 'DatasetTable_dataset': GET_DATASET, - 'DatasetTable_GlueTableProperties': GET_DATASET_TABLE, - 'Environment_networks': GET_NETWORK, - 'Environment_stack': GET_ENVIRONMENT, - 'EnvironmentSimplified_networks': GET_NETWORK, + # Organization related + get_resid('Organization', 'environments'): GET_ORGANIZATION, + get_resid('Organization', 'stats'): SKIP_MARK, + get_resid('Organization', 'userRoleInOrganization'): SKIP_MARK, } @@ -156,7 +232,7 @@ def test_unauthorized_tenant_permissions( @pytest.mark.parametrize( 'field', [ - pytest.param(field, id=f'{_type.name}_{field.name}') + pytest.param(field, id=get_resid(_type.name, field.name)) for _type, field in ALL_RESOLVERS if _type.name not in ['Query', 'Mutation'] # filter out top-level queries (don't print skip) ], @@ -168,9 +244,10 @@ def test_unauthorized_resource_permissions( field, request, ): - test_id = request.node.callspec.id - msg = f'{test_id} -> {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' - if test_id in IGNORE_NESTED_RESOLVERS: + res_id = request.node.callspec.id + expected_perm = NESTED_RESOLVERS_EXPECTED_PERMS.get(res_id, 'FOO_TEST_PERM') + msg = f'{res_id} -> {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' + if expected_perm in SKIP_MARK: pytest.skip(msg) logging.info(msg) @@ -188,5 +265,5 @@ def test_unauthorized_resource_permissions( resource_uri=ANY, username=username, groups=groups, - permission_name=EXPECTED_PERMS.get(test_id, 'FOO_TEST_PERM'), + permission_name=expected_perm, ) From 4c599ffd6cbb380f77c35bb003d87f068a4b4f96 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Mon, 25 Nov 2024 17:49:34 +0200 Subject: [PATCH 05/47] add more tests --- .../dataall/core/vpc/services/vpc_service.py | 19 +- .../api/storage_location/resolvers.py | 10 + tests/test_tenant_unauthorized.py | 332 ++++++++++-------- 3 files changed, 199 insertions(+), 162 deletions(-) diff --git a/backend/dataall/core/vpc/services/vpc_service.py b/backend/dataall/core/vpc/services/vpc_service.py index 87c9bd2ed..23cece5a6 100644 --- a/backend/dataall/core/vpc/services/vpc_service.py +++ b/backend/dataall/core/vpc/services/vpc_service.py @@ -90,12 +90,13 @@ def delete_network(uri): @staticmethod def get_environment_networks(environment_uri): with _session() as session: - vpc = VpcRepository.get_environment_networks(session=session, environment_uri=environment_uri) - ResourcePolicyService.check_user_resource_permission( - session=session, - username=get_context().username, - groups=get_context().groups, - resource_uri=vpc.vpcUri, - permission_name=GET_NETWORK, - ) - return vpc + vpcs = VpcRepository.get_environment_networks(session=session, environment_uri=environment_uri) + for vpc in vpcs: + ResourcePolicyService.check_user_resource_permission( + session=session, + username=get_context().username, + groups=get_context().groups, + resource_uri=vpc.vpcUri, + permission_name=GET_NETWORK, + ) + return vpcs diff --git a/backend/dataall/modules/s3_datasets/api/storage_location/resolvers.py b/backend/dataall/modules/s3_datasets/api/storage_location/resolvers.py index 3d6847029..a34e0b259 100644 --- a/backend/dataall/modules/s3_datasets/api/storage_location/resolvers.py +++ b/backend/dataall/modules/s3_datasets/api/storage_location/resolvers.py @@ -1,9 +1,12 @@ from dataall.base.api.context import Context +from dataall.base.context import get_context +from dataall.core.permissions.services.resource_policy_service import ResourcePolicyService from dataall.modules.catalog.db.glossary_repositories import GlossaryRepository from dataall.base.db.exceptions import RequiredParameter from dataall.base.feature_toggle_checker import is_feature_enabled from dataall.modules.s3_datasets.services.dataset_location_service import DatasetLocationService from dataall.modules.s3_datasets.db.dataset_models import DatasetStorageLocation, S3Dataset +from dataall.modules.s3_datasets.services.dataset_permissions import GET_DATASET def _validate_input(input: dict): @@ -47,6 +50,13 @@ def resolve_dataset(context, source: DatasetStorageLocation, **kwargs): if not source: return None with context.engine.scoped_session() as session: + ResourcePolicyService.check_user_resource_permission( + session=session, + username=get_context().username, + groups=get_context().groups, + resource_uri=source.datasetUri, + permission_name=GET_DATASET, + ) d = session.query(S3Dataset).get(source.datasetUri) return d diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index 60af508e9..ad7163689 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -13,6 +13,8 @@ from dataall.core.permissions.services.network_permissions import GET_NETWORK from dataall.core.permissions.services.organization_permissions import GET_ORGANIZATION from dataall.modules.datapipelines.services.datapipelines_permissions import GET_PIPELINE +from dataall.modules.mlstudio.services.mlstudio_permissions import GET_SGMSTUDIO_USER +from dataall.modules.notebooks.services.notebook_permissions import GET_NOTEBOOK from dataall.modules.s3_datasets.services.dataset_permissions import GET_DATASET, GET_DATASET_TABLE @@ -20,48 +22,53 @@ def resolver_id(type_name, field_name): return f'{type_name}_{field_name}' -class IgnoreReason(Enum): - ADMIN = 'admin action. No need for tenant permission check' - SUPPORT = 'tenant permissions do not apply to support notifications' - FEED = 'tenant permissions do not apply to support feed messages' - VOTES = 'tenant permissions do not apply to support votes' - BACKPORT = 'outside of this PR to be able to backport to v2.6.2' +SKIP_MARK = '@SKIP@' -def get_resid(type_name: str, field_name: str) -> str: +class IgnoreReason(Enum): + ADMIN = f'{SKIP_MARK} admin action. No need for tenant permission check' + SUPPORT = f'{SKIP_MARK} permissions do not apply to support notifications' + FEED = f'{SKIP_MARK} permissions do not apply to support feed messages' + VOTES = f'{SKIP_MARK} permissions do not apply to support votes' + BACKPORT = f'{SKIP_MARK} outside of this PR to be able to backport to v2.6.2' + INTRAMODULE = f'{SKIP_MARK} returns intra-module data' + PERMCHECK = f'{SKIP_MARK} checks user permissions for a particular feature' + CATALOG = f'{SKIP_MARK} catalog resources are public by design' + SIMPLIFIED = f'{SKIP_MARK} simplified response' + + +def field_id(type_name: str, field_name: str) -> str: return f'{type_name}_{field_name}' OPT_OUT_MUTATIONS = { # Admin actions - get_resid('Mutation', 'updateGroupTenantPermissions'): IgnoreReason.ADMIN.value, - get_resid('Mutation', 'updateSSMParameter'): IgnoreReason.ADMIN.value, - get_resid('Mutation', 'createQuicksightDataSourceSet'): IgnoreReason.ADMIN.value, - get_resid('Mutation', 'startMaintenanceWindow'): IgnoreReason.ADMIN.value, - get_resid('Mutation', 'stopMaintenanceWindow'): IgnoreReason.ADMIN.value, - get_resid('Mutation', 'startReindexCatalog'): IgnoreReason.ADMIN.value, - + field_id('Mutation', 'updateGroupTenantPermissions'): IgnoreReason.ADMIN.value, + field_id('Mutation', 'updateSSMParameter'): IgnoreReason.ADMIN.value, + field_id('Mutation', 'createQuicksightDataSourceSet'): IgnoreReason.ADMIN.value, + field_id('Mutation', 'startMaintenanceWindow'): IgnoreReason.ADMIN.value, + field_id('Mutation', 'stopMaintenanceWindow'): IgnoreReason.ADMIN.value, + field_id('Mutation', 'startReindexCatalog'): IgnoreReason.ADMIN.value, # Support-related actions - get_resid('Mutation', 'markNotificationAsRead'): IgnoreReason.SUPPORT.value, - get_resid('Mutation', 'deleteNotification'): IgnoreReason.SUPPORT.value, - get_resid('Mutation', 'postFeedMessage'): IgnoreReason.FEED.value, - get_resid('Mutation', 'upVote'): IgnoreReason.VOTES.value, - + field_id('Mutation', 'markNotificationAsRead'): IgnoreReason.SUPPORT.value, + field_id('Mutation', 'deleteNotification'): IgnoreReason.SUPPORT.value, + field_id('Mutation', 'postFeedMessage'): IgnoreReason.FEED.value, + field_id('Mutation', 'upVote'): IgnoreReason.VOTES.value, # Backport-related actions - get_resid('Mutation', 'createAttachedMetadataForm'): IgnoreReason.BACKPORT.value, - get_resid('Mutation', 'deleteAttachedMetadataForm'): IgnoreReason.BACKPORT.value, - get_resid('Mutation', 'createRedshiftConnection'): IgnoreReason.BACKPORT.value, - get_resid('Mutation', 'deleteRedshiftConnection'): IgnoreReason.BACKPORT.value, - get_resid('Mutation', 'addConnectionGroupPermission'): IgnoreReason.BACKPORT.value, - get_resid('Mutation', 'deleteConnectionGroupPermission'): IgnoreReason.BACKPORT.value, + field_id('Mutation', 'createAttachedMetadataForm'): IgnoreReason.BACKPORT.value, + field_id('Mutation', 'deleteAttachedMetadataForm'): IgnoreReason.BACKPORT.value, + field_id('Mutation', 'createRedshiftConnection'): IgnoreReason.BACKPORT.value, + field_id('Mutation', 'deleteRedshiftConnection'): IgnoreReason.BACKPORT.value, + field_id('Mutation', 'addConnectionGroupPermission'): IgnoreReason.BACKPORT.value, + field_id('Mutation', 'deleteConnectionGroupPermission'): IgnoreReason.BACKPORT.value, } OPT_IN_QUERIES = [ - get_resid('Query', 'generateEnvironmentAccessToken'), - get_resid('Query', 'getEnvironmentAssumeRoleUrl'), - get_resid('Query', 'getSagemakerStudioUserPresignedUrl'), - get_resid('Query', 'getSagemakerNotebookPresignedUrl'), - get_resid('Query', 'getDatasetAssumeRoleUrl'), + field_id('Query', 'generateEnvironmentAccessToken'), + field_id('Query', 'getEnvironmentAssumeRoleUrl'), + field_id('Query', 'getSagemakerStudioUserPresignedUrl'), + field_id('Query', 'getSagemakerNotebookPresignedUrl'), + field_id('Query', 'getDatasetAssumeRoleUrl'), ] ALL_RESOLVERS = {(_type, field) for _type in bootstrap().types for field in _type.fields if field.resolver} @@ -88,7 +95,7 @@ def mock_input_validation(mocker): @pytest.mark.parametrize( '_type,field', [ - pytest.param(_type, field, id=get_resid(_type.name, field.name)) + pytest.param(_type, field, id=field_id(_type.name, field.name)) for _type, field in ALL_RESOLVERS if _type.name in ['Query', 'Mutation'] ], @@ -104,11 +111,11 @@ def test_unauthorized_tenant_permissions( userNoTenantPermissions, groupNoTenantPermissions, ): - res_id = request.node.callspec.id - if _type.name == 'Mutation' and res_id in OPT_OUT_MUTATIONS.keys(): - pytest.skip(f'Skipping test for {res_id}: {OPT_OUT_MUTATIONS[res_id]}') - if _type.name == 'Query' and res_id not in OPT_IN_QUERIES: - pytest.skip(f'Skipping test for {res_id}: This Query does not require a tenant permission check.') + fid = request.node.callspec.id + if _type.name == 'Mutation' and fid in OPT_OUT_MUTATIONS.keys(): + pytest.skip(f'Skipping test for {fid}: {OPT_OUT_MUTATIONS[fid]}') + if _type.name == 'Query' and fid not in OPT_IN_QUERIES: + pytest.skip(f'Skipping test for {fid}: This Query does not require a tenant permission check.') assert_that(field.resolver).is_not_none() mock_local.context = RequestContext( db, userNoTenantPermissions.username, [groupNoTenantPermissions.groupUri], userNoTenantPermissions @@ -119,124 +126,143 @@ def test_unauthorized_tenant_permissions( assert_that(field.resolver).raises(TenantUnauthorized).when_called_with(**iargs).contains('UnauthorizedOperation') -SKIP_MARK = 'SKIP_MARK' - -NESTED_RESOLVERS_EXPECTED_PERMS = { - # AttachedMetadataForm related - get_resid('AttachedMetadataFormField', 'field'): SKIP_MARK, - get_resid('AttachedMetadataFormField', 'hasTenantPermissions'): SKIP_MARK, - get_resid('AttachedMetadataForm', 'entityName'): SKIP_MARK, - get_resid('AttachedMetadataForm', 'fields'): SKIP_MARK, - get_resid('AttachedMetadataForm', 'metadataForm'): SKIP_MARK, - - # Category related - get_resid('Category', 'associations'): SKIP_MARK, - get_resid('Category', 'categories'): SKIP_MARK, - get_resid('Category', 'children'): SKIP_MARK, - get_resid('Category', 'stats'): SKIP_MARK, - get_resid('Category', 'terms'): SKIP_MARK, - - # ConsumptionRole related - get_resid('ConsumptionRole', 'managedPolicies'): GET_ENVIRONMENT, - - # Dashboard related - get_resid('Dashboard', 'environment'): GET_ENVIRONMENT, - get_resid('Dashboard', 'terms'): SKIP_MARK, - get_resid('Dashboard', 'upvotes'): SKIP_MARK, - get_resid('Dashboard', 'userRoleForDashboard'): SKIP_MARK, - - # DataPipeline related - get_resid('DataPipeline', 'cloneUrlHttp'): SKIP_MARK, - get_resid('DataPipeline', 'developmentEnvironments'): SKIP_MARK, - get_resid('DataPipeline', 'environment'): GET_ENVIRONMENT, - get_resid('DataPipeline', 'organization'): GET_ORGANIZATION, - get_resid('DataPipeline', 'stack'): GET_PIPELINE, - get_resid('DataPipeline', 'userRoleForPipeline'): SKIP_MARK, - - # Dataset related - get_resid('DatasetBase', 'environment'): GET_ENVIRONMENT, - get_resid('DatasetBase', 'owners'): SKIP_MARK, - get_resid('DatasetBase', 'stack'): GET_DATASET, - get_resid('DatasetBase', 'stewards'): SKIP_MARK, - get_resid('DatasetBase', 'userRoleForDataset'): SKIP_MARK, - - # Dataset Profiling related - get_resid('DatasetProfilingRun', 'dataset'): GET_DATASET, - get_resid('DatasetProfilingRun', 'results'): SKIP_MARK, - get_resid('DatasetProfilingRun', 'status'): SKIP_MARK, - - # Dataset Storage and Table related - get_resid('DatasetStorageLocation', 'terms'): SKIP_MARK, - get_resid('DatasetTableColumn', 'terms'): SKIP_MARK, - get_resid('DatasetTable', 'GlueTableProperties'): GET_DATASET_TABLE, - get_resid('DatasetTable', 'columns'): SKIP_MARK, - get_resid('DatasetTable', 'dataset'): GET_DATASET, - get_resid('DatasetTable', 'terms'): SKIP_MARK, - - # Dataset specific - get_resid('Dataset', 'environment'): GET_ENVIRONMENT, - get_resid('Dataset', 'locations'): SKIP_MARK, - get_resid('Dataset', 'owners'): SKIP_MARK, - get_resid('Dataset', 'stack'): GET_DATASET, - get_resid('Dataset', 'statistics'): SKIP_MARK, - get_resid('Dataset', 'stewards'): SKIP_MARK, - get_resid('Dataset', 'tables'): SKIP_MARK, - get_resid('Dataset', 'terms'): SKIP_MARK, - get_resid('Dataset', 'userRoleForDataset'): SKIP_MARK, - - # Environment related - get_resid('EnvironmentSimplified', 'networks'): GET_NETWORK, - get_resid('EnvironmentSimplified', 'organization'): SKIP_MARK, - get_resid('Environment', 'networks'): GET_NETWORK, - get_resid('Environment', 'organization'): SKIP_MARK, - get_resid('Environment', 'parameters'): SKIP_MARK, - get_resid('Environment', 'stack'): GET_ENVIRONMENT, - get_resid('Environment', 'userRoleInEnvironment'): SKIP_MARK, - - # Feed and Glossary related - get_resid('Feed', 'messages'): SKIP_MARK, - get_resid('GlossaryTermLink', 'target'): SKIP_MARK, - get_resid('GlossaryTermLink', 'term'): SKIP_MARK, - get_resid('Glossary', 'associations'): SKIP_MARK, - get_resid('Glossary', 'categories'): SKIP_MARK, - get_resid('Glossary', 'children'): SKIP_MARK, - get_resid('Glossary', 'stats'): SKIP_MARK, - get_resid('Glossary', 'tree'): SKIP_MARK, - get_resid('Glossary', 'userRoleForGlossary'): SKIP_MARK, - - # Group and Metadata related - get_resid('Group', 'environmentPermissions'): SKIP_MARK, - get_resid('Group', 'tenantPermissions'): SKIP_MARK, - get_resid('MetadataFormField', 'glossaryNodeName'): SKIP_MARK, - get_resid('MetadataFormSearchResult', 'hasTenantPermissions'): SKIP_MARK, - get_resid('MetadataForm', 'fields'): SKIP_MARK, - get_resid('MetadataForm', 'homeEntityName'): SKIP_MARK, - get_resid('MetadataForm', 'userRole'): SKIP_MARK, - - # Omics related - get_resid('OmicsRun', 'environment'): GET_ENVIRONMENT, - get_resid('OmicsRun', 'organization'): GET_ORGANIZATION, - get_resid('OmicsRun', 'status'): SKIP_MARK, - get_resid('OmicsRun', 'workflow'): SKIP_MARK, - - # Organization related - get_resid('Organization', 'environments'): GET_ORGANIZATION, - get_resid('Organization', 'stats'): SKIP_MARK, - get_resid('Organization', 'userRoleInOrganization'): SKIP_MARK, +EXPECTED_RESOURCE_PERMS = { + field_id('AttachedMetadataFormField', 'field'): IgnoreReason.INTRAMODULE.value, + field_id('AttachedMetadataFormField', 'hasTenantPermissions'): IgnoreReason.PERMCHECK.value, + field_id('AttachedMetadataForm', 'entityName'): IgnoreReason.INTRAMODULE.value, + field_id('AttachedMetadataForm', 'fields'): IgnoreReason.INTRAMODULE.value, + field_id('AttachedMetadataForm', 'metadataForm'): IgnoreReason.INTRAMODULE.value, + field_id('Category', 'associations'): IgnoreReason.INTRAMODULE.value, + field_id('Category', 'categories'): IgnoreReason.INTRAMODULE.value, + field_id('Category', 'children'): IgnoreReason.INTRAMODULE.value, + field_id('Category', 'stats'): IgnoreReason.INTRAMODULE.value, + field_id('Category', 'terms'): IgnoreReason.INTRAMODULE.value, + field_id('ConsumptionRole', 'managedPolicies'): GET_ENVIRONMENT, + field_id('Dashboard', 'environment'): GET_ENVIRONMENT, + field_id('Dashboard', 'terms'): IgnoreReason.CATALOG.value, + field_id('Dashboard', 'upvotes'): IgnoreReason.VOTES.value, + field_id('Dashboard', 'userRoleForDashboard'): IgnoreReason.INTRAMODULE.value, + field_id('DataPipeline', 'cloneUrlHttp'): IgnoreReason.INTRAMODULE.value, + field_id('DataPipeline', 'developmentEnvironments'): IgnoreReason.INTRAMODULE.value, + field_id('DataPipeline', 'environment'): GET_ENVIRONMENT, + field_id('DataPipeline', 'organization'): GET_ORGANIZATION, + field_id('DataPipeline', 'stack'): GET_PIPELINE, + field_id('DataPipeline', 'userRoleForPipeline'): IgnoreReason.INTRAMODULE.value, + field_id('DatasetBase', 'environment'): GET_ENVIRONMENT, + field_id('DatasetBase', 'owners'): IgnoreReason.INTRAMODULE.value, + field_id('DatasetBase', 'stack'): GET_DATASET, + field_id('DatasetBase', 'stewards'): IgnoreReason.INTRAMODULE.value, + field_id('DatasetBase', 'userRoleForDataset'): IgnoreReason.INTRAMODULE.value, + field_id('DatasetProfilingRun', 'dataset'): GET_DATASET, + field_id('DatasetProfilingRun', 'results'): IgnoreReason.INTRAMODULE.value, + field_id('DatasetProfilingRun', 'status'): IgnoreReason.INTRAMODULE.value, + field_id('DatasetStorageLocation', 'dataset'): GET_DATASET, + field_id('DatasetStorageLocation', 'terms'): IgnoreReason.CATALOG.value, + field_id('DatasetTableColumn', 'terms'): IgnoreReason.CATALOG.value, + field_id('DatasetTable', 'GlueTableProperties'): GET_DATASET_TABLE, + field_id('DatasetTable', 'columns'): IgnoreReason.INTRAMODULE.value, + field_id('DatasetTable', 'dataset'): GET_DATASET, + field_id('DatasetTable', 'terms'): IgnoreReason.CATALOG.value, + field_id('Dataset', 'environment'): GET_ENVIRONMENT, + field_id('Dataset', 'locations'): IgnoreReason.INTRAMODULE.value, + field_id('Dataset', 'owners'): IgnoreReason.INTRAMODULE.value, + field_id('Dataset', 'stack'): GET_DATASET, + field_id('Dataset', 'statistics'): IgnoreReason.INTRAMODULE.value, + field_id('Dataset', 'stewards'): IgnoreReason.INTRAMODULE.value, + field_id('Dataset', 'tables'): IgnoreReason.INTRAMODULE.value, + field_id('Dataset', 'terms'): IgnoreReason.CATALOG.value, + field_id('Dataset', 'userRoleForDataset'): IgnoreReason.INTRAMODULE.value, + field_id('EnvironmentSimplified', 'networks'): GET_NETWORK, + field_id('EnvironmentSimplified', 'organization'): IgnoreReason.SIMPLIFIED.value, + field_id('Environment', 'networks'): GET_NETWORK, + field_id('Environment', 'organization'): IgnoreReason.SIMPLIFIED.value, + field_id('Environment', 'parameters'): IgnoreReason.INTRAMODULE.value, + field_id('Environment', 'stack'): GET_ENVIRONMENT, + field_id('Environment', 'userRoleInEnvironment'): IgnoreReason.INTRAMODULE.value, + field_id('Feed', 'messages'): IgnoreReason.FEED.value, + field_id('GlossaryTermLink', 'target'): IgnoreReason.CATALOG.value, + field_id('GlossaryTermLink', 'term'): IgnoreReason.CATALOG.value, + field_id('Glossary', 'associations'): IgnoreReason.CATALOG.value, + field_id('Glossary', 'categories'): IgnoreReason.CATALOG.value, + field_id('Glossary', 'children'): IgnoreReason.CATALOG.value, + field_id('Glossary', 'stats'): IgnoreReason.CATALOG.value, + field_id('Glossary', 'tree'): IgnoreReason.CATALOG.value, + field_id('Glossary', 'userRoleForGlossary'): IgnoreReason.CATALOG.value, + field_id('Group', 'environmentPermissions'): IgnoreReason.PERMCHECK.value, + field_id('Group', 'tenantPermissions'): IgnoreReason.PERMCHECK.value, + field_id('MetadataFormField', 'glossaryNodeName'): IgnoreReason.CATALOG.value, + field_id('MetadataFormSearchResult', 'hasTenantPermissions'): IgnoreReason.PERMCHECK.value, + field_id('MetadataForm', 'fields'): IgnoreReason.INTRAMODULE.value, + field_id('MetadataForm', 'homeEntityName'): IgnoreReason.INTRAMODULE.value, + field_id('MetadataForm', 'userRole'): IgnoreReason.INTRAMODULE.value, + field_id('OmicsRun', 'environment'): GET_ENVIRONMENT, + field_id('OmicsRun', 'organization'): GET_ORGANIZATION, + field_id('OmicsRun', 'status'): IgnoreReason.INTRAMODULE.value, + field_id('OmicsRun', 'workflow'): IgnoreReason.INTRAMODULE.value, + field_id('Organization', 'environments'): GET_ORGANIZATION, + field_id('Organization', 'stats'): IgnoreReason.INTRAMODULE.value, + field_id('Organization', 'userRoleInOrganization'): IgnoreReason.INTRAMODULE.value, + field_id('Permission', 'type'): IgnoreReason.INTRAMODULE.value, + field_id('RedshiftDataset', 'connection'): IgnoreReason.INTRAMODULE.value, + field_id('RedshiftDataset', 'environment'): GET_ENVIRONMENT, + field_id('RedshiftDataset', 'owners'): IgnoreReason.INTRAMODULE.value, + field_id('RedshiftDataset', 'stewards'): IgnoreReason.INTRAMODULE.value, + field_id('RedshiftDataset', 'terms'): IgnoreReason.CATALOG.value, + field_id('RedshiftDataset', 'upvotes'): IgnoreReason.VOTES.value, + field_id('RedshiftDataset', 'userRoleForDataset'): IgnoreReason.INTRAMODULE.value, + field_id('RedshiftDatasetTable', 'dataset'): IgnoreReason.INTRAMODULE.value, + field_id('RedshiftDatasetTable', 'terms'): IgnoreReason.CATALOG.value, + field_id('SagemakerNotebook', 'environment'): GET_ENVIRONMENT, + field_id('SagemakerNotebook', 'NotebookInstanceStatus'): IgnoreReason.INTRAMODULE.value, + field_id('SagemakerNotebook', 'organization'): GET_ORGANIZATION, + field_id('SagemakerNotebook', 'stack'): GET_NOTEBOOK, + field_id('SagemakerNotebook', 'userRoleForNotebook'): IgnoreReason.INTRAMODULE.value, + field_id('SagemakerStudioDomain', 'environment'): GET_ENVIRONMENT, + field_id('SagemakerStudioUser', 'environment'): GET_ENVIRONMENT, + field_id('SagemakerStudioUser', 'organization'): GET_ORGANIZATION, + field_id('SagemakerStudioUser', 'sagemakerStudioUserApps'): IgnoreReason.INTRAMODULE.value, + field_id('SagemakerStudioUser', 'sagemakerStudioUserStatus'): IgnoreReason.INTRAMODULE.value, + field_id('SagemakerStudioUser', 'stack'): GET_SGMSTUDIO_USER, + field_id('SagemakerStudioUser', 'userRoleForSagemakerStudioUser'): IgnoreReason.INTRAMODULE.value, + field_id('SharedDatabaseTableItem', 'sharedGlueDatabaseName'): IgnoreReason.INTRAMODULE.value, + field_id('ShareObject', 'canViewLogs'): IgnoreReason.INTRAMODULE.value, + field_id('ShareObject', 'dataset'): IgnoreReason.SIMPLIFIED.value, + field_id('ShareObject', 'environment'): GET_ENVIRONMENT, + field_id('ShareObject', 'existingSharedItems'): IgnoreReason.INTRAMODULE.value, + field_id('ShareObject', 'group'): IgnoreReason.INTRAMODULE.value, + field_id('ShareObject', 'items'): IgnoreReason.INTRAMODULE.value, + field_id('ShareObject', 'principal'): IgnoreReason.INTRAMODULE.value, + field_id('ShareObject', 'statistics'): IgnoreReason.INTRAMODULE.value, + field_id('ShareObject', 'userRoleForShareObject'): IgnoreReason.PERMCHECK.value, + field_id('Stack', 'canViewLogs'): IgnoreReason.INTRAMODULE.value, + field_id('Stack', 'EcsTaskId'): IgnoreReason.INTRAMODULE.value, + field_id('Stack', 'error'): IgnoreReason.INTRAMODULE.value, + field_id('Stack', 'events'): IgnoreReason.INTRAMODULE.value, + field_id('Stack', 'link'): IgnoreReason.INTRAMODULE.value, + field_id('Stack', 'outputs'): IgnoreReason.INTRAMODULE.value, + field_id('Stack', 'resources'): IgnoreReason.INTRAMODULE.value, + field_id('Term', 'associations'): IgnoreReason.INTRAMODULE.value, + field_id('Term', 'children'): IgnoreReason.INTRAMODULE.value, + field_id('Term', 'glossary'): IgnoreReason.INTRAMODULE.value, + field_id('Term', 'stats'): IgnoreReason.INTRAMODULE.value, + field_id('Worksheet', 'userRoleForWorksheet'): IgnoreReason.INTRAMODULE.value, } +PARAMS = [ + pytest.param(field, id=field_id(_type.name, field.name)) + for _type, field in ALL_RESOLVERS + if _type.name not in ['Query', 'Mutation'] # filter out top-level queries (don't print skip) +] +# ensure that all EXPECTED_RESOURCES_PERMS have a corresponding query (to avoid stale entries) and vice versa +assert_that(PARAMS).described_as('stale or missing EXPECTED_RESOURCE_PERMS detected').extracting(2).contains_only( + *EXPECTED_RESOURCE_PERMS.keys() +) + @patch('dataall.base.aws.sts.SessionHelper.remote_session') @patch('dataall.core.permissions.services.resource_policy_service.ResourcePolicyService.check_user_resource_permission') @patch('dataall.base.context._request_storage') -@pytest.mark.parametrize( - 'field', - [ - pytest.param(field, id=get_resid(_type.name, field.name)) - for _type, field in ALL_RESOLVERS - if _type.name not in ['Query', 'Mutation'] # filter out top-level queries (don't print skip) - ], -) +@pytest.mark.parametrize('field', PARAMS) def test_unauthorized_resource_permissions( mock_local, mock_check, @@ -244,11 +270,11 @@ def test_unauthorized_resource_permissions( field, request, ): - res_id = request.node.callspec.id - expected_perm = NESTED_RESOLVERS_EXPECTED_PERMS.get(res_id, 'FOO_TEST_PERM') - msg = f'{res_id} -> {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' - if expected_perm in SKIP_MARK: - pytest.skip(msg) + fid = request.node.callspec.id + expected_perm = EXPECTED_RESOURCE_PERMS.get(fid, 'NON_EXISTENT_PERM') + msg = f'{fid} -> {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' + if SKIP_MARK in expected_perm: + pytest.skip(msg + f' Reason: {expected_perm}') logging.info(msg) assert_that(field.resolver).is_not_none() From 77a8b821edf1d96b0d5456769f26992272133b12 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Tue, 26 Nov 2024 12:59:28 +0200 Subject: [PATCH 06/47] query.filter.all mock returns list --- tests/test_tenant_unauthorized.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index ad7163689..2bfd26c16 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -281,6 +281,7 @@ def test_unauthorized_resource_permissions( username = 'ausername' groups = ['agroup'] mock_local.context = RequestContext(MagicMock(), username, groups, 'auserid') + mock_local.context.db_engine.scoped_session().__enter__().query().filter().all.return_value = [MagicMock()] mock_check.side_effect = ResourceUnauthorized(groups, 'test_action', 'test_uri') iargs = {arg: MagicMock() for arg in inspect.signature(field.resolver).parameters.keys()} assert_that(field.resolver).described_as( From 1fa5c08204c726fb8ab6deb1544a3819a4187225 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Tue, 26 Nov 2024 15:45:45 +0200 Subject: [PATCH 07/47] assert called_once only without expecting to raise as some resolvers are filtering out resources --- tests/test_tenant_unauthorized.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index 2bfd26c16..d1de35b46 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -1,5 +1,6 @@ import inspect import logging +from contextlib import suppress from enum import Enum from unittest.mock import MagicMock, patch, ANY @@ -284,9 +285,8 @@ def test_unauthorized_resource_permissions( mock_local.context.db_engine.scoped_session().__enter__().query().filter().all.return_value = [MagicMock()] mock_check.side_effect = ResourceUnauthorized(groups, 'test_action', 'test_uri') iargs = {arg: MagicMock() for arg in inspect.signature(field.resolver).parameters.keys()} - assert_that(field.resolver).described_as( - f'resolver code: {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' - ).raises(ResourceUnauthorized).when_called_with(**iargs).contains('UnauthorizedOperation', 'test_action') + with suppress(ResourceUnauthorized): + field.resolver(**iargs) mock_check.assert_called_once_with( session=ANY, resource_uri=ANY, From 5dad8dc1c1c45f245c15416c6c6247521731457d Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Tue, 26 Nov 2024 15:46:03 +0200 Subject: [PATCH 08/47] filter out networks --- .../dataall/core/vpc/services/vpc_service.py | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/backend/dataall/core/vpc/services/vpc_service.py b/backend/dataall/core/vpc/services/vpc_service.py index 23cece5a6..fbdf8f092 100644 --- a/backend/dataall/core/vpc/services/vpc_service.py +++ b/backend/dataall/core/vpc/services/vpc_service.py @@ -1,5 +1,8 @@ +import logging + from dataall.base.context import get_context from dataall.base.db import exceptions +from dataall.base.db.exceptions import ResourceUnauthorized from dataall.core.permissions.services.group_policy_service import GroupPolicyService from dataall.core.environment.db.environment_repositories import EnvironmentRepository from dataall.core.activity.db.activity_models import Activity @@ -11,6 +14,8 @@ from dataall.core.permissions.services.environment_permissions import CREATE_NETWORK from dataall.core.permissions.services.tenant_permissions import MANAGE_ENVIRONMENTS +log = logging.getLogger(__name__) + def _session(): return get_context().db_engine.scoped_session() @@ -90,13 +95,19 @@ def delete_network(uri): @staticmethod def get_environment_networks(environment_uri): with _session() as session: - vpcs = VpcRepository.get_environment_networks(session=session, environment_uri=environment_uri) - for vpc in vpcs: - ResourcePolicyService.check_user_resource_permission( - session=session, - username=get_context().username, - groups=get_context().groups, - resource_uri=vpc.vpcUri, - permission_name=GET_NETWORK, - ) - return vpcs + nets = [] + all_nets = VpcRepository.get_environment_networks(session=session, environment_uri=environment_uri) + for net in all_nets: + try: + ResourcePolicyService.check_user_resource_permission( + session=session, + username=get_context().username, + groups=get_context().groups, + resource_uri=net.vpcUri, + permission_name=GET_NETWORK, + ) + except ResourceUnauthorized as exc: + log.info(exc) + else: + nets += net + return nets From f11e3f5edfb2d797e28d79f9672cdd3cf52ea79a Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Tue, 26 Nov 2024 15:53:40 +0200 Subject: [PATCH 09/47] ignore reason --- tests/test_tenant_unauthorized.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index d1de35b46..125cf702f 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -113,8 +113,8 @@ def test_unauthorized_tenant_permissions( groupNoTenantPermissions, ): fid = request.node.callspec.id - if _type.name == 'Mutation' and fid in OPT_OUT_MUTATIONS.keys(): - pytest.skip(f'Skipping test for {fid}: {OPT_OUT_MUTATIONS[fid]}') + if _type.name == 'Mutation' and (reason := OPT_OUT_MUTATIONS.get(fid)): + pytest.skip(f'Skipping test for {fid}: {reason}') if _type.name == 'Query' and fid not in OPT_IN_QUERIES: pytest.skip(f'Skipping test for {fid}: This Query does not require a tenant permission check.') assert_that(field.resolver).is_not_none() From 0f12c31dc9ca192a54f2a4d3036af546c5ea3f59 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Tue, 26 Nov 2024 17:23:09 +0200 Subject: [PATCH 10/47] fix check order --- backend/dataall/core/stacks/services/stack_service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/dataall/core/stacks/services/stack_service.py b/backend/dataall/core/stacks/services/stack_service.py index 657b3f51a..46bacd555 100644 --- a/backend/dataall/core/stacks/services/stack_service.py +++ b/backend/dataall/core/stacks/services/stack_service.py @@ -68,7 +68,6 @@ class StackService: def resolve_parent_obj_stack(targetUri: str, targetType: str, environmentUri: str): context = get_context() with context.db_engine.scoped_session() as session: - env: Environment = EnvironmentRepository.get_environment_by_uri(session, environmentUri) ResourcePolicyService.check_user_resource_permission( session=session, username=context.username, @@ -76,6 +75,7 @@ def resolve_parent_obj_stack(targetUri: str, targetType: str, environmentUri: st resource_uri=targetUri, permission_name=TargetType.get_resource_read_permission_name(targetType), ) + env: Environment = EnvironmentRepository.get_environment_by_uri(session, environmentUri) stack: Stack = StackRepository.find_stack_by_target_uri(session, target_uri=targetUri) if not stack: stack = Stack( From 377bef8ead1fce4f446fe6463ef6d3efd1ec1554 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Wed, 27 Nov 2024 11:44:09 +0200 Subject: [PATCH 11/47] fix find_environment_by_uri invocation --- backend/dataall/modules/datasets_base/api/resolvers.py | 3 +-- .../modules/redshift_datasets/api/datasets/resolvers.py | 3 +-- backend/dataall/modules/s3_datasets/api/dataset/resolvers.py | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/backend/dataall/modules/datasets_base/api/resolvers.py b/backend/dataall/modules/datasets_base/api/resolvers.py index 48e424ad1..017256ae6 100644 --- a/backend/dataall/modules/datasets_base/api/resolvers.py +++ b/backend/dataall/modules/datasets_base/api/resolvers.py @@ -58,8 +58,7 @@ def get_dataset_organization(context, source: DatasetBase, **kwargs): def get_dataset_environment(context, source: DatasetBase, **kwargs): if not source: return None - with context.engine.scoped_session() as session: - return EnvironmentService.find_environment_by_uri(session, uri=source.environmentUri) + return EnvironmentService.find_environment_by_uri(uri=source.environmentUri) def get_dataset_owners_group(context, source: DatasetBase, **kwargs): diff --git a/backend/dataall/modules/redshift_datasets/api/datasets/resolvers.py b/backend/dataall/modules/redshift_datasets/api/datasets/resolvers.py index 06683c2c0..aca1b2e79 100644 --- a/backend/dataall/modules/redshift_datasets/api/datasets/resolvers.py +++ b/backend/dataall/modules/redshift_datasets/api/datasets/resolvers.py @@ -87,8 +87,7 @@ def resolve_dataset_environment( ): # TODO- duplicated with S3 datasets - follow-up PR if not source: return None - with context.engine.scoped_session() as session: - return EnvironmentService.find_environment_by_uri(session, uri=source.environmentUri) + return EnvironmentService.find_environment_by_uri(uri=source.environmentUri) def resolve_dataset_owners_group( diff --git a/backend/dataall/modules/s3_datasets/api/dataset/resolvers.py b/backend/dataall/modules/s3_datasets/api/dataset/resolvers.py index 7808cb253..ef8acdbb7 100644 --- a/backend/dataall/modules/s3_datasets/api/dataset/resolvers.py +++ b/backend/dataall/modules/s3_datasets/api/dataset/resolvers.py @@ -85,8 +85,7 @@ def get_dataset_organization(context, source: S3Dataset, **kwargs): def get_dataset_environment(context, source: S3Dataset, **kwargs): if not source: return None - with context.engine.scoped_session() as session: - return EnvironmentService.find_environment_by_uri(session, uri=source.environmentUri) + return EnvironmentService.find_environment_by_uri(uri=source.environmentUri) def get_dataset_owners_group(context, source: S3Dataset, **kwargs): From 32a85cc7c32b99131167f8b31e5d45c66ed1efde Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Wed, 27 Nov 2024 14:52:39 +0200 Subject: [PATCH 12/47] remove get_dataset check --- backend/dataall/modules/s3_datasets/services/dataset_service.py | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/dataall/modules/s3_datasets/services/dataset_service.py b/backend/dataall/modules/s3_datasets/services/dataset_service.py index 252a709ef..226645318 100644 --- a/backend/dataall/modules/s3_datasets/services/dataset_service.py +++ b/backend/dataall/modules/s3_datasets/services/dataset_service.py @@ -235,7 +235,6 @@ def import_dataset(uri, admin_group, data): return DatasetService.create_dataset(uri=uri, admin_group=admin_group, data=data) @staticmethod - @ResourcePolicyService.has_resource_permission(GET_DATASET) def get_dataset(uri): context = get_context() with context.db_engine.scoped_session() as session: From a5ffea9d9ea35ab12ddbb3adb6c9802e692613eb Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Wed, 27 Nov 2024 15:50:17 +0200 Subject: [PATCH 13/47] fix test client to allow errors --- tests_new/integration_tests/client.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/tests_new/integration_tests/client.py b/tests_new/integration_tests/client.py index bef02d39e..dc7e4a999 100644 --- a/tests_new/integration_tests/client.py +++ b/tests_new/integration_tests/client.py @@ -1,12 +1,16 @@ -import requests +import logging import os import uuid +from pprint import pformat from urllib.parse import parse_qs, urlparse + +import requests from munch import DefaultMunch -from retrying import retry -from integration_tests.errors import GqlError from oauthlib.oauth2 import WebApplicationClient from requests_oauthlib import OAuth2Session +from retrying import retry + +from integration_tests.errors import GqlError ENVNAME = os.getenv('ENVNAME', 'dev') @@ -28,15 +32,19 @@ def __init__(self, username, password): wait_random_min=1000, wait_random_max=3000, ) - def query(self, query: str): + def query(self, query: dict): graphql_endpoint = os.path.join(os.environ['API_ENDPOINT'], 'graphql', 'api') headers = {'accesskeyid': 'none', 'SecretKey': 'none', 'Authorization': f'Bearer {self.access_token}'} r = requests.post(graphql_endpoint, json=query, headers=headers) - if errors := r.json().get('errors'): - raise GqlError(errors) + response = r.json() + have_data = any([bool(value) for key, value in response.get('data', {}).items()]) + if errors := response.get('errors'): + if have_data: + logging.warning(f'{query=} returned both data and errors:\n {pformat(response)}') + else: + raise GqlError(errors) r.raise_for_status() - - return DefaultMunch.fromDict(r.json()) + return DefaultMunch.fromDict(response) def _get_jwt_tokens(self): token = uuid.uuid4() From 46d134b988d0f5f353ffd8e93faeb21489a8d3e1 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Thu, 28 Nov 2024 13:09:53 +0200 Subject: [PATCH 14/47] fix test client --- tests_new/integration_tests/client.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests_new/integration_tests/client.py b/tests_new/integration_tests/client.py index dc7e4a999..cb756ce9e 100644 --- a/tests_new/integration_tests/client.py +++ b/tests_new/integration_tests/client.py @@ -37,9 +37,8 @@ def query(self, query: dict): headers = {'accesskeyid': 'none', 'SecretKey': 'none', 'Authorization': f'Bearer {self.access_token}'} r = requests.post(graphql_endpoint, json=query, headers=headers) response = r.json() - have_data = any([bool(value) for key, value in response.get('data', {}).items()]) if errors := response.get('errors'): - if have_data: + if any((response.get('data', {}) or {}).values()): # check if there are data logging.warning(f'{query=} returned both data and errors:\n {pformat(response)}') else: raise GqlError(errors) From c2e49493a9d3d0b4688a9519b5d455223ae0a789 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Fri, 29 Nov 2024 14:03:56 +0200 Subject: [PATCH 15/47] fix datasetlist --- frontend/src/modules/DatasetsBase/views/DatasetList.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/src/modules/DatasetsBase/views/DatasetList.js b/frontend/src/modules/DatasetsBase/views/DatasetList.js index b6835a547..f3611a239 100644 --- a/frontend/src/modules/DatasetsBase/views/DatasetList.js +++ b/frontend/src/modules/DatasetsBase/views/DatasetList.js @@ -94,10 +94,12 @@ const DatasetList = () => { const fetchItems = useCallback(async () => { setLoading(true); const response = await client.query(listDatasets({ filter })); - if (!response.errors) { + if (response.data.listDatasets !== null) { setItems(response.data.listDatasets); } else { - dispatch({ type: SET_ERROR, error: response.errors[0].message }); + response.errors.forEach((err) => + dispatch({ type: SET_ERROR, error: err.message }) + ); } setLoading(false); }, [client, dispatch, filter]); From 49fd52704ba5b4e6d443a5b9d6d1ce171c2191cf Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Fri, 29 Nov 2024 14:14:49 +0200 Subject: [PATCH 16/47] fix dataset view --- frontend/src/modules/S3_Datasets/components/DatasetOverview.js | 2 +- frontend/src/modules/S3_Datasets/views/DatasetView.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/modules/S3_Datasets/components/DatasetOverview.js b/frontend/src/modules/S3_Datasets/components/DatasetOverview.js index 351e8a3ce..0599d33b2 100644 --- a/frontend/src/modules/S3_Datasets/components/DatasetOverview.js +++ b/frontend/src/modules/S3_Datasets/components/DatasetOverview.js @@ -26,7 +26,7 @@ export const DatasetOverview = (props) => { { const fetchItem = useCallback(async () => { setLoading(true); const response = await client.query(getDataset(params.uri)); - if (!response.errors && response.data.getDataset !== null) { + if (response.data.getDataset !== null) { setDataset(response.data.getDataset); setIsAdmin( ['BusinessOwner', 'Admin', 'DataSteward', 'Creator'].indexOf( From c22fea30c003bda426a0d99ec2566c4ad378c373 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Fri, 29 Nov 2024 14:58:15 +0200 Subject: [PATCH 17/47] add pipeline exceptions for checkov --- .checkov.baseline | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.checkov.baseline b/.checkov.baseline index 19875f2e3..796f224f6 100644 --- a/.checkov.baseline +++ b/.checkov.baseline @@ -613,6 +613,25 @@ } ] }, + { + "file": "/checkov_pipeline_synth.json", + "findings": [ + { + "resource": "AWS::IAM::Role.PipelineRoleDCFDBB91", + "check_ids": [ + "CKV_AWS_107", + "CKV_AWS_108", + "CKV_AWS_111" + ] + }, + { + "resource": "AWS::S3::Bucket.thistableartifactsbucketDB1C8C64", + "check_ids": [ + "CKV_AWS_18" + ] + } + ] + }, { "file": "/frontend/docker/prod/Dockerfile", "findings": [ From 4671a4ee937d858b71ea26983bbea663eb7a49e2 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Fri, 29 Nov 2024 15:07:33 +0200 Subject: [PATCH 18/47] fix tests --- tests/test_tenant_unauthorized.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index 125cf702f..359957c95 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -154,7 +154,7 @@ def test_unauthorized_tenant_permissions( field_id('DatasetBase', 'stack'): GET_DATASET, field_id('DatasetBase', 'stewards'): IgnoreReason.INTRAMODULE.value, field_id('DatasetBase', 'userRoleForDataset'): IgnoreReason.INTRAMODULE.value, - field_id('DatasetProfilingRun', 'dataset'): GET_DATASET, + field_id('DatasetProfilingRun', 'dataset'): IgnoreReason.INTRAMODULE.value, field_id('DatasetProfilingRun', 'results'): IgnoreReason.INTRAMODULE.value, field_id('DatasetProfilingRun', 'status'): IgnoreReason.INTRAMODULE.value, field_id('DatasetStorageLocation', 'dataset'): GET_DATASET, @@ -162,7 +162,7 @@ def test_unauthorized_tenant_permissions( field_id('DatasetTableColumn', 'terms'): IgnoreReason.CATALOG.value, field_id('DatasetTable', 'GlueTableProperties'): GET_DATASET_TABLE, field_id('DatasetTable', 'columns'): IgnoreReason.INTRAMODULE.value, - field_id('DatasetTable', 'dataset'): GET_DATASET, + field_id('DatasetTable', 'dataset'): IgnoreReason.INTRAMODULE.value, field_id('DatasetTable', 'terms'): IgnoreReason.CATALOG.value, field_id('Dataset', 'environment'): GET_ENVIRONMENT, field_id('Dataset', 'locations'): IgnoreReason.INTRAMODULE.value, From 5e83ea65de12f46d84e6b5b2620bab1435aa29b9 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Fri, 29 Nov 2024 15:45:58 +0200 Subject: [PATCH 19/47] fix folder ui --- frontend/src/modules/Folders/components/FolderOverview.js | 8 ++++---- .../src/modules/Folders/components/FolderS3Properties.js | 2 +- frontend/src/modules/Folders/views/FolderView.js | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/frontend/src/modules/Folders/components/FolderOverview.js b/frontend/src/modules/Folders/components/FolderOverview.js index 98dcfc84b..c1b6c469c 100644 --- a/frontend/src/modules/Folders/components/FolderOverview.js +++ b/frontend/src/modules/Folders/components/FolderOverview.js @@ -27,11 +27,11 @@ export const FolderOverview = (props) => { diff --git a/frontend/src/modules/Folders/components/FolderS3Properties.js b/frontend/src/modules/Folders/components/FolderS3Properties.js index 5118896f5..1447d0fe8 100644 --- a/frontend/src/modules/Folders/components/FolderS3Properties.js +++ b/frontend/src/modules/Folders/components/FolderS3Properties.js @@ -9,7 +9,7 @@ import { export const FolderS3Properties = (props) => { const { folder } = props; - + if (folder.dataset === null) return null; return ( diff --git a/frontend/src/modules/Folders/views/FolderView.js b/frontend/src/modules/Folders/views/FolderView.js index 184b258bf..23f882c69 100644 --- a/frontend/src/modules/Folders/views/FolderView.js +++ b/frontend/src/modules/Folders/views/FolderView.js @@ -233,11 +233,11 @@ const FolderView = () => { const fetchItem = useCallback(async () => { setLoading(true); const response = await client.query(getDatasetStorageLocation(params.uri)); - if (!response.errors && response.data.getDatasetStorageLocation !== null) { + if (response.data.getDatasetStorageLocation !== null) { setFolder(response.data.getDatasetStorageLocation); setIsAdmin( ['Creator', 'Admin', 'Owner'].indexOf( - response.data.getDatasetStorageLocation.dataset.userRoleForDataset + response.data.getDatasetStorageLocation.dataset?.userRoleForDataset ) !== -1 ); } else { From 3c54f3cd9ed2e3e8244dba0b30c1f2d8cc2d6e57 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Fri, 29 Nov 2024 16:50:40 +0200 Subject: [PATCH 20/47] use explicit tenant perms --- tests/test_tenant_unauthorized.py | 270 +++++++++++++++++++++++++++--- 1 file changed, 250 insertions(+), 20 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index 359957c95..5273bb401 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -13,10 +13,19 @@ from dataall.core.permissions.services.environment_permissions import GET_ENVIRONMENT from dataall.core.permissions.services.network_permissions import GET_NETWORK from dataall.core.permissions.services.organization_permissions import GET_ORGANIZATION -from dataall.modules.datapipelines.services.datapipelines_permissions import GET_PIPELINE -from dataall.modules.mlstudio.services.mlstudio_permissions import GET_SGMSTUDIO_USER -from dataall.modules.notebooks.services.notebook_permissions import GET_NOTEBOOK -from dataall.modules.s3_datasets.services.dataset_permissions import GET_DATASET, GET_DATASET_TABLE +from dataall.core.permissions.services.tenant_permissions import MANAGE_ENVIRONMENTS, MANAGE_ORGANIZATIONS +from dataall.core.permissions.services.tenant_policy_service import TenantPolicyService +from dataall.modules.catalog.services.glossaries_permissions import MANAGE_GLOSSARIES +from dataall.modules.dashboards.services.dashboard_permissions import MANAGE_DASHBOARDS +from dataall.modules.datapipelines.services.datapipelines_permissions import GET_PIPELINE, MANAGE_PIPELINES +from dataall.modules.metadata_forms.services.metadata_form_permissions import MANAGE_METADATA_FORMS +from dataall.modules.mlstudio.services.mlstudio_permissions import GET_SGMSTUDIO_USER, MANAGE_SGMSTUDIO_USERS +from dataall.modules.notebooks.services.notebook_permissions import GET_NOTEBOOK, MANAGE_NOTEBOOKS +from dataall.modules.omics.services.omics_permissions import MANAGE_OMICS_RUNS +from dataall.modules.redshift_datasets.services.redshift_dataset_permissions import MANAGE_REDSHIFT_DATASETS +from dataall.modules.s3_datasets.services.dataset_permissions import GET_DATASET, GET_DATASET_TABLE, MANAGE_DATASETS +from dataall.modules.shares_base.services.share_permissions import MANAGE_SHARES +from dataall.modules.worksheets.services.worksheet_permissions import MANAGE_WORKSHEETS def resolver_id(type_name, field_name): @@ -36,13 +45,237 @@ class IgnoreReason(Enum): PERMCHECK = f'{SKIP_MARK} checks user permissions for a particular feature' CATALOG = f'{SKIP_MARK} catalog resources are public by design' SIMPLIFIED = f'{SKIP_MARK} simplified response' + NOTIMPLEMENTED = f'{SKIP_MARK} not implemented' def field_id(type_name: str, field_name: str) -> str: return f'{type_name}_{field_name}' -OPT_OUT_MUTATIONS = { +ALL_RESOLVERS = {(_type, field) for _type in bootstrap().types for field in _type.fields if field.resolver} + +TOP_LEVEL_QUERIES = { + field_id('Mutation', 'DisableDataSubscriptions'): MANAGE_ENVIRONMENTS, + field_id('Mutation', 'addConsumptionRoleToEnvironment'): MANAGE_ENVIRONMENTS, + field_id('Mutation', 'addRedshiftDatasetTables'): MANAGE_REDSHIFT_DATASETS, + field_id('Mutation', 'addSharedItem'): MANAGE_SHARES, + field_id('Mutation', 'approveDashboardShare'): MANAGE_DASHBOARDS, + field_id('Mutation', 'approveShareExtension'): MANAGE_SHARES, + field_id('Mutation', 'approveShareObject'): MANAGE_SHARES, + field_id('Mutation', 'approveTermAssociation'): MANAGE_GLOSSARIES, + field_id('Mutation', 'archiveOrganization'): MANAGE_ORGANIZATIONS, + field_id('Mutation', 'batchMetadataFormFieldUpdates'): MANAGE_METADATA_FORMS, + field_id('Mutation', 'cancelShareExtension'): MANAGE_SHARES, + field_id('Mutation', 'createCategory'): MANAGE_GLOSSARIES, + field_id('Mutation', 'createDataPipeline'): MANAGE_PIPELINES, + field_id('Mutation', 'createDataPipelineEnvironment'): MANAGE_PIPELINES, + field_id('Mutation', 'createDataset'): MANAGE_DATASETS, + field_id('Mutation', 'createDatasetStorageLocation'): MANAGE_DATASETS, + field_id('Mutation', 'createEnvironment'): MANAGE_ENVIRONMENTS, + field_id('Mutation', 'createGlossary'): MANAGE_GLOSSARIES, + field_id('Mutation', 'createMetadataForm'): MANAGE_METADATA_FORMS, + field_id('Mutation', 'createMetadataFormFields'): MANAGE_METADATA_FORMS, + field_id('Mutation', 'createMetadataFormVersion'): MANAGE_METADATA_FORMS, + field_id('Mutation', 'createNetwork'): MANAGE_ENVIRONMENTS, + field_id('Mutation', 'createOmicsRun'): MANAGE_OMICS_RUNS, + field_id('Mutation', 'createOrganization'): MANAGE_ORGANIZATIONS, + field_id('Mutation', 'createSagemakerNotebook'): MANAGE_NOTEBOOKS, + field_id('Mutation', 'createSagemakerStudioUser'): MANAGE_SGMSTUDIO_USERS, + field_id('Mutation', 'createShareObject'): MANAGE_SHARES, + field_id('Mutation', 'createTableDataFilter'): MANAGE_DATASETS, + field_id('Mutation', 'createTerm'): MANAGE_GLOSSARIES, + field_id('Mutation', 'createWorksheet'): MANAGE_WORKSHEETS, + field_id('Mutation', 'deleteCategory'): MANAGE_GLOSSARIES, + field_id('Mutation', 'deleteDashboard'): MANAGE_DASHBOARDS, + field_id('Mutation', 'deleteDataPipeline'): MANAGE_PIPELINES, + field_id('Mutation', 'deleteDataPipelineEnvironment'): MANAGE_PIPELINES, + field_id('Mutation', 'deleteDataset'): MANAGE_DATASETS, + field_id('Mutation', 'deleteDatasetStorageLocation'): MANAGE_DATASETS, + field_id('Mutation', 'deleteDatasetTable'): MANAGE_DATASETS, + field_id('Mutation', 'deleteEnvironment'): MANAGE_ENVIRONMENTS, + field_id('Mutation', 'deleteGlossary'): MANAGE_GLOSSARIES, + field_id('Mutation', 'deleteMetadataForm'): MANAGE_METADATA_FORMS, + field_id('Mutation', 'deleteMetadataFormField'): MANAGE_METADATA_FORMS, + field_id('Mutation', 'deleteMetadataFormVersion'): MANAGE_METADATA_FORMS, + field_id('Mutation', 'deleteNetwork'): MANAGE_ENVIRONMENTS, + field_id('Mutation', 'deleteOmicsRun'): MANAGE_OMICS_RUNS, + field_id('Mutation', 'deleteRedshiftDataset'): MANAGE_REDSHIFT_DATASETS, + field_id('Mutation', 'deleteRedshiftDatasetTable'): MANAGE_REDSHIFT_DATASETS, + field_id('Mutation', 'deleteSagemakerNotebook'): MANAGE_NOTEBOOKS, + field_id('Mutation', 'deleteSagemakerStudioUser'): MANAGE_SGMSTUDIO_USERS, + field_id('Mutation', 'deleteShareObject'): MANAGE_SHARES, + field_id('Mutation', 'deleteTableDataFilter'): MANAGE_DATASETS, + field_id('Mutation', 'deleteTerm'): MANAGE_GLOSSARIES, + field_id('Mutation', 'deleteWorksheet'): MANAGE_WORKSHEETS, + field_id('Mutation', 'dismissTermAssociation'): MANAGE_GLOSSARIES, + field_id('Mutation', 'enableDataSubscriptions'): MANAGE_ENVIRONMENTS, + field_id('Mutation', 'generateDatasetAccessToken'): MANAGE_DATASETS, + field_id('Mutation', 'importDashboard'): MANAGE_DASHBOARDS, + field_id('Mutation', 'importDataset'): MANAGE_DATASETS, + field_id('Mutation', 'importRedshiftDataset'): MANAGE_REDSHIFT_DATASETS, + field_id('Mutation', 'inviteGroupOnEnvironment'): MANAGE_ENVIRONMENTS, + field_id('Mutation', 'inviteGroupToOrganization'): MANAGE_ORGANIZATIONS, + field_id('Mutation', 'reApplyItemsShareObject'): MANAGE_SHARES, + field_id('Mutation', 'reApplyShareObjectItemsOnDataset'): MANAGE_DATASETS, + field_id('Mutation', 'rejectDashboardShare'): MANAGE_DASHBOARDS, + field_id('Mutation', 'rejectShareObject'): MANAGE_SHARES, + field_id('Mutation', 'removeConsumptionRoleFromEnvironment'): MANAGE_ENVIRONMENTS, + field_id('Mutation', 'removeGroupFromEnvironment'): MANAGE_ENVIRONMENTS, + field_id('Mutation', 'removeGroupFromOrganization'): MANAGE_ORGANIZATIONS, + field_id('Mutation', 'removeShareItemFilter'): MANAGE_SHARES, + field_id('Mutation', 'removeSharedItem'): MANAGE_SHARES, + field_id('Mutation', 'requestDashboardShare'): MANAGE_DASHBOARDS, + field_id('Mutation', 'revokeItemsShareObject'): MANAGE_SHARES, + field_id('Mutation', 'startDatasetProfilingRun'): MANAGE_DATASETS, + field_id('Mutation', 'startGlueCrawler'): MANAGE_DATASETS, + field_id('Mutation', 'startSagemakerNotebook'): MANAGE_NOTEBOOKS, + field_id('Mutation', 'stopSagemakerNotebook'): MANAGE_NOTEBOOKS, + field_id('Mutation', 'submitShareExtension'): MANAGE_SHARES, + field_id('Mutation', 'submitShareObject'): MANAGE_SHARES, + field_id('Mutation', 'syncDatasetTableColumns'): MANAGE_DATASETS, + field_id('Mutation', 'syncTables'): MANAGE_DATASETS, + field_id('Mutation', 'updateCategory'): MANAGE_GLOSSARIES, + field_id('Mutation', 'updateConsumptionRole'): MANAGE_ENVIRONMENTS, + field_id('Mutation', 'updateDashboard'): MANAGE_DASHBOARDS, + field_id('Mutation', 'updateDataPipeline'): MANAGE_PIPELINES, + field_id('Mutation', 'updateDataPipelineEnvironment'): MANAGE_PIPELINES, + field_id('Mutation', 'updateDataset'): MANAGE_DATASETS, + field_id('Mutation', 'updateDatasetStorageLocation'): MANAGE_DATASETS, + field_id('Mutation', 'updateDatasetTable'): MANAGE_DATASETS, + field_id('Mutation', 'updateDatasetTableColumn'): MANAGE_DATASETS, + field_id('Mutation', 'updateEnvironment'): MANAGE_ENVIRONMENTS, + field_id('Mutation', 'updateGlossary'): MANAGE_GLOSSARIES, + field_id('Mutation', 'updateGroupEnvironmentPermissions'): MANAGE_ENVIRONMENTS, + field_id('Mutation', 'updateKeyValueTags'): MANAGE_ENVIRONMENTS, + field_id('Mutation', 'updateOrganization'): MANAGE_ORGANIZATIONS, + field_id('Mutation', 'updateOrganizationGroup'): MANAGE_ORGANIZATIONS, + field_id('Mutation', 'updateRedshiftDataset'): MANAGE_REDSHIFT_DATASETS, + field_id('Mutation', 'updateRedshiftDatasetTable'): MANAGE_REDSHIFT_DATASETS, + field_id('Mutation', 'updateShareExpirationPeriod'): MANAGE_SHARES, + field_id('Mutation', 'updateShareExtensionReason'): MANAGE_SHARES, + field_id('Mutation', 'updateShareItemFilters'): MANAGE_SHARES, + field_id('Mutation', 'updateShareRejectReason'): MANAGE_SHARES, + field_id('Mutation', 'updateShareRequestReason'): MANAGE_SHARES, + field_id('Mutation', 'updateStack'): MANAGE_ENVIRONMENTS, + field_id('Mutation', 'updateTerm'): MANAGE_GLOSSARIES, + field_id('Mutation', 'updateWorksheet'): MANAGE_WORKSHEETS, + field_id('Mutation', 'verifyDatasetShareObjects'): MANAGE_DATASETS, + field_id('Mutation', 'verifyItemsShareObject'): MANAGE_SHARES, + field_id('Query', 'countDeletedNotifications'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'countReadNotifications'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'countUnreadNotifications'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'countUpVotes'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'generateEnvironmentAccessToken'): MANAGE_ENVIRONMENTS, + field_id('Query', 'getAttachedMetadataForm'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getAuthorSession'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getCDKExecPolicyPresignedUrl'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getConsumptionRolePolicies'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getDashboard'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getDataPipeline'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getDataPipelineCredsLinux'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getDataset'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getDatasetAssumeRoleUrl'): MANAGE_DATASETS, + field_id('Query', 'getDatasetPresignedUrl'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getDatasetSharedAssumeRoleUrl'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getDatasetStorageLocation'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getDatasetTable'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getDatasetTableProfilingRun'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getEntityMetadataFormPermissions'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getEnvironment'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getEnvironmentAssumeRoleUrl'): MANAGE_ENVIRONMENTS, + field_id('Query', 'getEnvironmentMLStudioDomain'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getFeed'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getGlossary'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getGroup'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getGroupsForUser'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getMaintenanceWindowStatus'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getMetadataForm'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getMonitoringDashboardId'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getMonitoringVPCConnectionId'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getOmicsWorkflow'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getOrganization'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getPivotRoleExternalId'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getPivotRoleName'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getPivotRolePresignedUrl'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getPlatformAuthorSession'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getPlatformReaderSession'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getReaderSession'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getRedshiftDataset'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getRedshiftDatasetTable'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getRedshiftDatasetTableColumns'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getS3ConsumptionData'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getSagemakerNotebook'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getSagemakerNotebookPresignedUrl'): MANAGE_NOTEBOOKS, + field_id('Query', 'getSagemakerStudioUser'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getSagemakerStudioUserPresignedUrl'): MANAGE_SGMSTUDIO_USERS, + field_id('Query', 'getShareItemDataFilters'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getShareLogs'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getShareObject'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getShareRequestsFromMe'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getShareRequestsToMe'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getSharedDatasetTables'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getStack'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getStackLogs'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getTrustAccount'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getVote'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'getWorksheet'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listAllConsumptionRoles'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listAllEnvironmentConsumptionRoles'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listAllEnvironmentGroups'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listAllGroups'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listAttachedMetadataForms'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listConnectionGroupNoPermissions'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listConnectionGroupPermissions'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listDashboardShares'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listDataPipelines'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listDatasetTableColumns'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listDatasetTableProfilingRuns'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listDatasetTables'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listDatasets'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listDatasetsCreatedInEnvironment'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listEntityMetadataForms'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listEnvironmentConsumptionRoles'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listEnvironmentGroupInvitationPermissions'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listEnvironmentGroups'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listEnvironmentInvitedGroups'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listEnvironmentNetworks'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listEnvironmentRedshiftConnections'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listEnvironments'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listGlossaries'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listGroups'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listInviteOrganizationPermissionsWithDescriptions'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listKeyValueTags'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listMetadataFormVersions'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listNotifications'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listOmicsRuns'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listOmicsWorkflows'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listOrganizationGroupPermissions'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listOrganizationGroups'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listOrganizations'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listOwnedDatasets'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listRedshiftConnectionSchemas'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listRedshiftDatasetTables'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listRedshiftSchemaDatasetTables'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listRedshiftSchemaTables'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listS3DatasetsOwnedByEnvGroup'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listS3DatasetsSharedWithEnvGroup'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listSagemakerNotebooks'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listSagemakerStudioUsers'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listSharedDatasetTableColumns'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listTableDataFilters'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listTableDataFiltersByAttached'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listTenantGroups'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listTenantPermissions'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listUserMetadataForms'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listUsersForGroup'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listValidEnvironments'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'listWorksheets'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'previewTable'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'queryEnums'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'runAthenaSqlQuery'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'searchDashboards'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'searchEnvironmentDataItems'): IgnoreReason.NOTIMPLEMENTED.value, + field_id('Query', 'searchGlossary'): IgnoreReason.NOTIMPLEMENTED.value, # Admin actions field_id('Mutation', 'updateGroupTenantPermissions'): IgnoreReason.ADMIN.value, field_id('Mutation', 'updateSSMParameter'): IgnoreReason.ADMIN.value, @@ -64,16 +297,6 @@ def field_id(type_name: str, field_name: str) -> str: field_id('Mutation', 'deleteConnectionGroupPermission'): IgnoreReason.BACKPORT.value, } -OPT_IN_QUERIES = [ - field_id('Query', 'generateEnvironmentAccessToken'), - field_id('Query', 'getEnvironmentAssumeRoleUrl'), - field_id('Query', 'getSagemakerStudioUserPresignedUrl'), - field_id('Query', 'getSagemakerNotebookPresignedUrl'), - field_id('Query', 'getDatasetAssumeRoleUrl'), -] - -ALL_RESOLVERS = {(_type, field) for _type in bootstrap().types for field in _type.fields if field.resolver} - @pytest.fixture(scope='function') def mock_input_validation(mocker): @@ -101,9 +324,11 @@ def mock_input_validation(mocker): if _type.name in ['Query', 'Mutation'] ], ) +@patch('dataall.core.permissions.services.tenant_policy_service.TenantPolicyService.check_user_tenant_permission', wraps=TenantPolicyService.check_user_tenant_permission) @patch('dataall.base.context._request_storage') def test_unauthorized_tenant_permissions( mock_local, + spy_check, _type, field, request, @@ -113,18 +338,23 @@ def test_unauthorized_tenant_permissions( groupNoTenantPermissions, ): fid = request.node.callspec.id - if _type.name == 'Mutation' and (reason := OPT_OUT_MUTATIONS.get(fid)): - pytest.skip(f'Skipping test for {fid}: {reason}') - if _type.name == 'Query' and fid not in OPT_IN_QUERIES: - pytest.skip(f'Skipping test for {fid}: This Query does not require a tenant permission check.') + expected_perm = TOP_LEVEL_QUERIES.get(fid, 'NON_EXISTENT_PERM') + msg = f'{fid} -> {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' + if SKIP_MARK in expected_perm: + pytest.skip(msg + f' Reason: {expected_perm}') + logging.info(msg) + assert_that(field.resolver).is_not_none() + groups = [groupNoTenantPermissions.groupUri] + username = userNoTenantPermissions.username mock_local.context = RequestContext( - db, userNoTenantPermissions.username, [groupNoTenantPermissions.groupUri], userNoTenantPermissions + db, username, groups, userNoTenantPermissions ) # Mocking arguments iargs = {arg: MagicMock() for arg in inspect.signature(field.resolver).parameters.keys()} # Assert Unauthorized exception is raised assert_that(field.resolver).raises(TenantUnauthorized).when_called_with(**iargs).contains('UnauthorizedOperation') + spy_check.assert_called_once_with(session=ANY, username=username, groups=groups, tenant_name=ANY, permission_name=expected_perm) EXPECTED_RESOURCE_PERMS = { From 6a15647a8a7f7d2097127b2c1652ad706622b81f Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Fri, 29 Nov 2024 17:45:27 +0200 Subject: [PATCH 21/47] make use of testdata --- tests/test_tenant_unauthorized.py | 495 +++++++++++++++--------------- 1 file changed, 254 insertions(+), 241 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index 5273bb401..aed638c44 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -1,7 +1,9 @@ import inspect import logging from contextlib import suppress +from dataclasses import dataclass from enum import Enum +from typing import Mapping from unittest.mock import MagicMock, patch, ANY import pytest @@ -54,247 +56,257 @@ def field_id(type_name: str, field_name: str) -> str: ALL_RESOLVERS = {(_type, field) for _type in bootstrap().types for field in _type.fields if field.resolver} -TOP_LEVEL_QUERIES = { - field_id('Mutation', 'DisableDataSubscriptions'): MANAGE_ENVIRONMENTS, - field_id('Mutation', 'addConsumptionRoleToEnvironment'): MANAGE_ENVIRONMENTS, - field_id('Mutation', 'addRedshiftDatasetTables'): MANAGE_REDSHIFT_DATASETS, - field_id('Mutation', 'addSharedItem'): MANAGE_SHARES, - field_id('Mutation', 'approveDashboardShare'): MANAGE_DASHBOARDS, - field_id('Mutation', 'approveShareExtension'): MANAGE_SHARES, - field_id('Mutation', 'approveShareObject'): MANAGE_SHARES, - field_id('Mutation', 'approveTermAssociation'): MANAGE_GLOSSARIES, - field_id('Mutation', 'archiveOrganization'): MANAGE_ORGANIZATIONS, - field_id('Mutation', 'batchMetadataFormFieldUpdates'): MANAGE_METADATA_FORMS, - field_id('Mutation', 'cancelShareExtension'): MANAGE_SHARES, - field_id('Mutation', 'createCategory'): MANAGE_GLOSSARIES, - field_id('Mutation', 'createDataPipeline'): MANAGE_PIPELINES, - field_id('Mutation', 'createDataPipelineEnvironment'): MANAGE_PIPELINES, - field_id('Mutation', 'createDataset'): MANAGE_DATASETS, - field_id('Mutation', 'createDatasetStorageLocation'): MANAGE_DATASETS, - field_id('Mutation', 'createEnvironment'): MANAGE_ENVIRONMENTS, - field_id('Mutation', 'createGlossary'): MANAGE_GLOSSARIES, - field_id('Mutation', 'createMetadataForm'): MANAGE_METADATA_FORMS, - field_id('Mutation', 'createMetadataFormFields'): MANAGE_METADATA_FORMS, - field_id('Mutation', 'createMetadataFormVersion'): MANAGE_METADATA_FORMS, - field_id('Mutation', 'createNetwork'): MANAGE_ENVIRONMENTS, - field_id('Mutation', 'createOmicsRun'): MANAGE_OMICS_RUNS, - field_id('Mutation', 'createOrganization'): MANAGE_ORGANIZATIONS, - field_id('Mutation', 'createSagemakerNotebook'): MANAGE_NOTEBOOKS, - field_id('Mutation', 'createSagemakerStudioUser'): MANAGE_SGMSTUDIO_USERS, - field_id('Mutation', 'createShareObject'): MANAGE_SHARES, - field_id('Mutation', 'createTableDataFilter'): MANAGE_DATASETS, - field_id('Mutation', 'createTerm'): MANAGE_GLOSSARIES, - field_id('Mutation', 'createWorksheet'): MANAGE_WORKSHEETS, - field_id('Mutation', 'deleteCategory'): MANAGE_GLOSSARIES, - field_id('Mutation', 'deleteDashboard'): MANAGE_DASHBOARDS, - field_id('Mutation', 'deleteDataPipeline'): MANAGE_PIPELINES, - field_id('Mutation', 'deleteDataPipelineEnvironment'): MANAGE_PIPELINES, - field_id('Mutation', 'deleteDataset'): MANAGE_DATASETS, - field_id('Mutation', 'deleteDatasetStorageLocation'): MANAGE_DATASETS, - field_id('Mutation', 'deleteDatasetTable'): MANAGE_DATASETS, - field_id('Mutation', 'deleteEnvironment'): MANAGE_ENVIRONMENTS, - field_id('Mutation', 'deleteGlossary'): MANAGE_GLOSSARIES, - field_id('Mutation', 'deleteMetadataForm'): MANAGE_METADATA_FORMS, - field_id('Mutation', 'deleteMetadataFormField'): MANAGE_METADATA_FORMS, - field_id('Mutation', 'deleteMetadataFormVersion'): MANAGE_METADATA_FORMS, - field_id('Mutation', 'deleteNetwork'): MANAGE_ENVIRONMENTS, - field_id('Mutation', 'deleteOmicsRun'): MANAGE_OMICS_RUNS, - field_id('Mutation', 'deleteRedshiftDataset'): MANAGE_REDSHIFT_DATASETS, - field_id('Mutation', 'deleteRedshiftDatasetTable'): MANAGE_REDSHIFT_DATASETS, - field_id('Mutation', 'deleteSagemakerNotebook'): MANAGE_NOTEBOOKS, - field_id('Mutation', 'deleteSagemakerStudioUser'): MANAGE_SGMSTUDIO_USERS, - field_id('Mutation', 'deleteShareObject'): MANAGE_SHARES, - field_id('Mutation', 'deleteTableDataFilter'): MANAGE_DATASETS, - field_id('Mutation', 'deleteTerm'): MANAGE_GLOSSARIES, - field_id('Mutation', 'deleteWorksheet'): MANAGE_WORKSHEETS, - field_id('Mutation', 'dismissTermAssociation'): MANAGE_GLOSSARIES, - field_id('Mutation', 'enableDataSubscriptions'): MANAGE_ENVIRONMENTS, - field_id('Mutation', 'generateDatasetAccessToken'): MANAGE_DATASETS, - field_id('Mutation', 'importDashboard'): MANAGE_DASHBOARDS, - field_id('Mutation', 'importDataset'): MANAGE_DATASETS, - field_id('Mutation', 'importRedshiftDataset'): MANAGE_REDSHIFT_DATASETS, - field_id('Mutation', 'inviteGroupOnEnvironment'): MANAGE_ENVIRONMENTS, - field_id('Mutation', 'inviteGroupToOrganization'): MANAGE_ORGANIZATIONS, - field_id('Mutation', 'reApplyItemsShareObject'): MANAGE_SHARES, - field_id('Mutation', 'reApplyShareObjectItemsOnDataset'): MANAGE_DATASETS, - field_id('Mutation', 'rejectDashboardShare'): MANAGE_DASHBOARDS, - field_id('Mutation', 'rejectShareObject'): MANAGE_SHARES, - field_id('Mutation', 'removeConsumptionRoleFromEnvironment'): MANAGE_ENVIRONMENTS, - field_id('Mutation', 'removeGroupFromEnvironment'): MANAGE_ENVIRONMENTS, - field_id('Mutation', 'removeGroupFromOrganization'): MANAGE_ORGANIZATIONS, - field_id('Mutation', 'removeShareItemFilter'): MANAGE_SHARES, - field_id('Mutation', 'removeSharedItem'): MANAGE_SHARES, - field_id('Mutation', 'requestDashboardShare'): MANAGE_DASHBOARDS, - field_id('Mutation', 'revokeItemsShareObject'): MANAGE_SHARES, - field_id('Mutation', 'startDatasetProfilingRun'): MANAGE_DATASETS, - field_id('Mutation', 'startGlueCrawler'): MANAGE_DATASETS, - field_id('Mutation', 'startSagemakerNotebook'): MANAGE_NOTEBOOKS, - field_id('Mutation', 'stopSagemakerNotebook'): MANAGE_NOTEBOOKS, - field_id('Mutation', 'submitShareExtension'): MANAGE_SHARES, - field_id('Mutation', 'submitShareObject'): MANAGE_SHARES, - field_id('Mutation', 'syncDatasetTableColumns'): MANAGE_DATASETS, - field_id('Mutation', 'syncTables'): MANAGE_DATASETS, - field_id('Mutation', 'updateCategory'): MANAGE_GLOSSARIES, - field_id('Mutation', 'updateConsumptionRole'): MANAGE_ENVIRONMENTS, - field_id('Mutation', 'updateDashboard'): MANAGE_DASHBOARDS, - field_id('Mutation', 'updateDataPipeline'): MANAGE_PIPELINES, - field_id('Mutation', 'updateDataPipelineEnvironment'): MANAGE_PIPELINES, - field_id('Mutation', 'updateDataset'): MANAGE_DATASETS, - field_id('Mutation', 'updateDatasetStorageLocation'): MANAGE_DATASETS, - field_id('Mutation', 'updateDatasetTable'): MANAGE_DATASETS, - field_id('Mutation', 'updateDatasetTableColumn'): MANAGE_DATASETS, - field_id('Mutation', 'updateEnvironment'): MANAGE_ENVIRONMENTS, - field_id('Mutation', 'updateGlossary'): MANAGE_GLOSSARIES, - field_id('Mutation', 'updateGroupEnvironmentPermissions'): MANAGE_ENVIRONMENTS, - field_id('Mutation', 'updateKeyValueTags'): MANAGE_ENVIRONMENTS, - field_id('Mutation', 'updateOrganization'): MANAGE_ORGANIZATIONS, - field_id('Mutation', 'updateOrganizationGroup'): MANAGE_ORGANIZATIONS, - field_id('Mutation', 'updateRedshiftDataset'): MANAGE_REDSHIFT_DATASETS, - field_id('Mutation', 'updateRedshiftDatasetTable'): MANAGE_REDSHIFT_DATASETS, - field_id('Mutation', 'updateShareExpirationPeriod'): MANAGE_SHARES, - field_id('Mutation', 'updateShareExtensionReason'): MANAGE_SHARES, - field_id('Mutation', 'updateShareItemFilters'): MANAGE_SHARES, - field_id('Mutation', 'updateShareRejectReason'): MANAGE_SHARES, - field_id('Mutation', 'updateShareRequestReason'): MANAGE_SHARES, - field_id('Mutation', 'updateStack'): MANAGE_ENVIRONMENTS, - field_id('Mutation', 'updateTerm'): MANAGE_GLOSSARIES, - field_id('Mutation', 'updateWorksheet'): MANAGE_WORKSHEETS, - field_id('Mutation', 'verifyDatasetShareObjects'): MANAGE_DATASETS, - field_id('Mutation', 'verifyItemsShareObject'): MANAGE_SHARES, - field_id('Query', 'countDeletedNotifications'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'countReadNotifications'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'countUnreadNotifications'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'countUpVotes'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'generateEnvironmentAccessToken'): MANAGE_ENVIRONMENTS, - field_id('Query', 'getAttachedMetadataForm'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getAuthorSession'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getCDKExecPolicyPresignedUrl'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getConsumptionRolePolicies'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getDashboard'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getDataPipeline'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getDataPipelineCredsLinux'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getDataset'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getDatasetAssumeRoleUrl'): MANAGE_DATASETS, - field_id('Query', 'getDatasetPresignedUrl'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getDatasetSharedAssumeRoleUrl'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getDatasetStorageLocation'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getDatasetTable'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getDatasetTableProfilingRun'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getEntityMetadataFormPermissions'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getEnvironment'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getEnvironmentAssumeRoleUrl'): MANAGE_ENVIRONMENTS, - field_id('Query', 'getEnvironmentMLStudioDomain'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getFeed'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getGlossary'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getGroup'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getGroupsForUser'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getMaintenanceWindowStatus'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getMetadataForm'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getMonitoringDashboardId'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getMonitoringVPCConnectionId'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getOmicsWorkflow'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getOrganization'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getPivotRoleExternalId'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getPivotRoleName'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getPivotRolePresignedUrl'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getPlatformAuthorSession'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getPlatformReaderSession'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getReaderSession'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getRedshiftDataset'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getRedshiftDatasetTable'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getRedshiftDatasetTableColumns'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getS3ConsumptionData'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getSagemakerNotebook'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getSagemakerNotebookPresignedUrl'): MANAGE_NOTEBOOKS, - field_id('Query', 'getSagemakerStudioUser'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getSagemakerStudioUserPresignedUrl'): MANAGE_SGMSTUDIO_USERS, - field_id('Query', 'getShareItemDataFilters'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getShareLogs'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getShareObject'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getShareRequestsFromMe'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getShareRequestsToMe'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getSharedDatasetTables'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getStack'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getStackLogs'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getTrustAccount'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getVote'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'getWorksheet'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listAllConsumptionRoles'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listAllEnvironmentConsumptionRoles'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listAllEnvironmentGroups'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listAllGroups'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listAttachedMetadataForms'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listConnectionGroupNoPermissions'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listConnectionGroupPermissions'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listDashboardShares'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listDataPipelines'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listDatasetTableColumns'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listDatasetTableProfilingRuns'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listDatasetTables'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listDatasets'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listDatasetsCreatedInEnvironment'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listEntityMetadataForms'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listEnvironmentConsumptionRoles'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listEnvironmentGroupInvitationPermissions'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listEnvironmentGroups'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listEnvironmentInvitedGroups'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listEnvironmentNetworks'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listEnvironmentRedshiftConnections'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listEnvironments'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listGlossaries'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listGroups'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listInviteOrganizationPermissionsWithDescriptions'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listKeyValueTags'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listMetadataFormVersions'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listNotifications'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listOmicsRuns'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listOmicsWorkflows'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listOrganizationGroupPermissions'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listOrganizationGroups'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listOrganizations'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listOwnedDatasets'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listRedshiftConnectionSchemas'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listRedshiftDatasetTables'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listRedshiftSchemaDatasetTables'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listRedshiftSchemaTables'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listS3DatasetsOwnedByEnvGroup'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listS3DatasetsSharedWithEnvGroup'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listSagemakerNotebooks'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listSagemakerStudioUsers'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listSharedDatasetTableColumns'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listTableDataFilters'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listTableDataFiltersByAttached'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listTenantGroups'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listTenantPermissions'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listUserMetadataForms'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listUsersForGroup'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listValidEnvironments'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'listWorksheets'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'previewTable'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'queryEnums'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'runAthenaSqlQuery'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'searchDashboards'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'searchEnvironmentDataItems'): IgnoreReason.NOTIMPLEMENTED.value, - field_id('Query', 'searchGlossary'): IgnoreReason.NOTIMPLEMENTED.value, + +@dataclass +class TestData: + resource_ignore: IgnoreReason = IgnoreReason.NOTIMPLEMENTED + resource_perm: str = None + tenant_ignore: IgnoreReason = IgnoreReason.NOTIMPLEMENTED + tenant_perm: str = None + + +TENANT_CHECKS: Mapping[str, TestData] = { + field_id('Mutation', 'DisableDataSubscriptions'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), + field_id('Mutation', 'addConsumptionRoleToEnvironment'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), + field_id('Mutation', 'addRedshiftDatasetTables'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), + field_id('Mutation', 'addSharedItem'): TestData(tenant_perm=MANAGE_SHARES), + field_id('Mutation', 'approveDashboardShare'): TestData(tenant_perm=MANAGE_DASHBOARDS), + field_id('Mutation', 'approveShareExtension'): TestData(tenant_perm=MANAGE_SHARES), + field_id('Mutation', 'approveShareObject'): TestData(tenant_perm=MANAGE_SHARES), + field_id('Mutation', 'approveTermAssociation'): TestData(tenant_perm=MANAGE_GLOSSARIES), + field_id('Mutation', 'archiveOrganization'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), + field_id('Mutation', 'batchMetadataFormFieldUpdates'): TestData(tenant_perm=MANAGE_METADATA_FORMS), + field_id('Mutation', 'cancelShareExtension'): TestData(tenant_perm=MANAGE_SHARES), + field_id('Mutation', 'createCategory'): TestData(tenant_perm=MANAGE_GLOSSARIES), + field_id('Mutation', 'createDataPipeline'): TestData(tenant_perm=MANAGE_PIPELINES), + field_id('Mutation', 'createDataPipelineEnvironment'): TestData(tenant_perm=MANAGE_PIPELINES), + field_id('Mutation', 'createDataset'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'createDatasetStorageLocation'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'createEnvironment'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), + field_id('Mutation', 'createGlossary'): TestData(tenant_perm=MANAGE_GLOSSARIES), + field_id('Mutation', 'createMetadataForm'): TestData(tenant_perm=MANAGE_METADATA_FORMS), + field_id('Mutation', 'createMetadataFormFields'): TestData(tenant_perm=MANAGE_METADATA_FORMS), + field_id('Mutation', 'createMetadataFormVersion'): TestData(tenant_perm=MANAGE_METADATA_FORMS), + field_id('Mutation', 'createNetwork'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), + field_id('Mutation', 'createOmicsRun'): TestData(tenant_perm=MANAGE_OMICS_RUNS), + field_id('Mutation', 'createOrganization'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), + field_id('Mutation', 'createSagemakerNotebook'): TestData(tenant_perm=MANAGE_NOTEBOOKS), + field_id('Mutation', 'createSagemakerStudioUser'): TestData(tenant_perm=MANAGE_SGMSTUDIO_USERS), + field_id('Mutation', 'createShareObject'): TestData(tenant_perm=MANAGE_SHARES), + field_id('Mutation', 'createTableDataFilter'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'createTerm'): TestData(tenant_perm=MANAGE_GLOSSARIES), + field_id('Mutation', 'createWorksheet'): TestData(tenant_perm=MANAGE_WORKSHEETS), + field_id('Mutation', 'deleteCategory'): TestData(tenant_perm=MANAGE_GLOSSARIES), + field_id('Mutation', 'deleteDashboard'): TestData(tenant_perm=MANAGE_DASHBOARDS), + field_id('Mutation', 'deleteDataPipeline'): TestData(tenant_perm=MANAGE_PIPELINES), + field_id('Mutation', 'deleteDataPipelineEnvironment'): TestData(tenant_perm=MANAGE_PIPELINES), + field_id('Mutation', 'deleteDataset'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'deleteDatasetStorageLocation'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'deleteDatasetTable'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'deleteEnvironment'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), + field_id('Mutation', 'deleteGlossary'): TestData(tenant_perm=MANAGE_GLOSSARIES), + field_id('Mutation', 'deleteMetadataForm'): TestData(tenant_perm=MANAGE_METADATA_FORMS), + field_id('Mutation', 'deleteMetadataFormField'): TestData(tenant_perm=MANAGE_METADATA_FORMS), + field_id('Mutation', 'deleteMetadataFormVersion'): TestData(tenant_perm=MANAGE_METADATA_FORMS), + field_id('Mutation', 'deleteNetwork'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), + field_id('Mutation', 'deleteOmicsRun'): TestData(tenant_perm=MANAGE_OMICS_RUNS), + field_id('Mutation', 'deleteRedshiftDataset'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), + field_id('Mutation', 'deleteRedshiftDatasetTable'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), + field_id('Mutation', 'deleteSagemakerNotebook'): TestData(tenant_perm=MANAGE_NOTEBOOKS), + field_id('Mutation', 'deleteSagemakerStudioUser'): TestData(tenant_perm=MANAGE_SGMSTUDIO_USERS), + field_id('Mutation', 'deleteShareObject'): TestData(tenant_perm=MANAGE_SHARES), + field_id('Mutation', 'deleteTableDataFilter'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'deleteTerm'): TestData(tenant_perm=MANAGE_GLOSSARIES), + field_id('Mutation', 'deleteWorksheet'): TestData(tenant_perm=MANAGE_WORKSHEETS), + field_id('Mutation', 'dismissTermAssociation'): TestData(tenant_perm=MANAGE_GLOSSARIES), + field_id('Mutation', 'enableDataSubscriptions'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), + field_id('Mutation', 'generateDatasetAccessToken'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'importDashboard'): TestData(tenant_perm=MANAGE_DASHBOARDS), + field_id('Mutation', 'importDataset'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'importRedshiftDataset'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), + field_id('Mutation', 'inviteGroupOnEnvironment'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), + field_id('Mutation', 'inviteGroupToOrganization'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), + field_id('Mutation', 'reApplyItemsShareObject'): TestData(tenant_perm=MANAGE_SHARES), + field_id('Mutation', 'reApplyShareObjectItemsOnDataset'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'rejectDashboardShare'): TestData(tenant_perm=MANAGE_DASHBOARDS), + field_id('Mutation', 'rejectShareObject'): TestData(tenant_perm=MANAGE_SHARES), + field_id('Mutation', 'removeConsumptionRoleFromEnvironment'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), + field_id('Mutation', 'removeGroupFromEnvironment'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), + field_id('Mutation', 'removeGroupFromOrganization'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), + field_id('Mutation', 'removeShareItemFilter'): TestData(tenant_perm=MANAGE_SHARES), + field_id('Mutation', 'removeSharedItem'): TestData(tenant_perm=MANAGE_SHARES), + field_id('Mutation', 'requestDashboardShare'): TestData(tenant_perm=MANAGE_DASHBOARDS), + field_id('Mutation', 'revokeItemsShareObject'): TestData(tenant_perm=MANAGE_SHARES), + field_id('Mutation', 'startDatasetProfilingRun'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'startGlueCrawler'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'startSagemakerNotebook'): TestData(tenant_perm=MANAGE_NOTEBOOKS), + field_id('Mutation', 'stopSagemakerNotebook'): TestData(tenant_perm=MANAGE_NOTEBOOKS), + field_id('Mutation', 'submitShareExtension'): TestData(tenant_perm=MANAGE_SHARES), + field_id('Mutation', 'submitShareObject'): TestData(tenant_perm=MANAGE_SHARES), + field_id('Mutation', 'syncDatasetTableColumns'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'syncTables'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'updateCategory'): TestData(tenant_perm=MANAGE_GLOSSARIES), + field_id('Mutation', 'updateConsumptionRole'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), + field_id('Mutation', 'updateDashboard'): TestData(tenant_perm=MANAGE_DASHBOARDS), + field_id('Mutation', 'updateDataPipeline'): TestData(tenant_perm=MANAGE_PIPELINES), + field_id('Mutation', 'updateDataPipelineEnvironment'): TestData(tenant_perm=MANAGE_PIPELINES), + field_id('Mutation', 'updateDataset'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'updateDatasetStorageLocation'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'updateDatasetTable'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'updateDatasetTableColumn'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'updateEnvironment'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), + field_id('Mutation', 'updateGlossary'): TestData(tenant_perm=MANAGE_GLOSSARIES), + field_id('Mutation', 'updateGroupEnvironmentPermissions'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), + field_id('Mutation', 'updateKeyValueTags'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), + field_id('Mutation', 'updateOrganization'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), + field_id('Mutation', 'updateOrganizationGroup'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), + field_id('Mutation', 'updateRedshiftDataset'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), + field_id('Mutation', 'updateRedshiftDatasetTable'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), + field_id('Mutation', 'updateShareExpirationPeriod'): TestData(tenant_perm=MANAGE_SHARES), + field_id('Mutation', 'updateShareExtensionReason'): TestData(tenant_perm=MANAGE_SHARES), + field_id('Mutation', 'updateShareItemFilters'): TestData(tenant_perm=MANAGE_SHARES), + field_id('Mutation', 'updateShareRejectReason'): TestData(tenant_perm=MANAGE_SHARES), + field_id('Mutation', 'updateShareRequestReason'): TestData(tenant_perm=MANAGE_SHARES), + field_id('Mutation', 'updateStack'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), + field_id('Mutation', 'updateTerm'): TestData(tenant_perm=MANAGE_GLOSSARIES), + field_id('Mutation', 'updateWorksheet'): TestData(tenant_perm=MANAGE_WORKSHEETS), + field_id('Mutation', 'verifyDatasetShareObjects'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'verifyItemsShareObject'): TestData(tenant_perm=MANAGE_SHARES), + field_id('Query', 'countDeletedNotifications'): TestData(), + field_id('Query', 'countReadNotifications'): TestData(), + field_id('Query', 'countUnreadNotifications'): TestData(), + field_id('Query', 'countUpVotes'): TestData(), + field_id('Query', 'generateEnvironmentAccessToken'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), + field_id('Query', 'getAttachedMetadataForm'): TestData(), + field_id('Query', 'getAuthorSession'): TestData(), + field_id('Query', 'getCDKExecPolicyPresignedUrl'): TestData(), + field_id('Query', 'getConsumptionRolePolicies'): TestData(), + field_id('Query', 'getDashboard'): TestData(), + field_id('Query', 'getDataPipeline'): TestData(), + field_id('Query', 'getDataPipelineCredsLinux'): TestData(), + field_id('Query', 'getDataset'): TestData(), + field_id('Query', 'getDatasetAssumeRoleUrl'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Query', 'getDatasetPresignedUrl'): TestData(), + field_id('Query', 'getDatasetSharedAssumeRoleUrl'): TestData(), + field_id('Query', 'getDatasetStorageLocation'): TestData(), + field_id('Query', 'getDatasetTable'): TestData(), + field_id('Query', 'getDatasetTableProfilingRun'): TestData(), + field_id('Query', 'getEntityMetadataFormPermissions'): TestData(), + field_id('Query', 'getEnvironment'): TestData(), + field_id('Query', 'getEnvironmentAssumeRoleUrl'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), + field_id('Query', 'getEnvironmentMLStudioDomain'): TestData(), + field_id('Query', 'getFeed'): TestData(), + field_id('Query', 'getGlossary'): TestData(), + field_id('Query', 'getGroup'): TestData(), + field_id('Query', 'getGroupsForUser'): TestData(), + field_id('Query', 'getMaintenanceWindowStatus'): TestData(), + field_id('Query', 'getMetadataForm'): TestData(), + field_id('Query', 'getMonitoringDashboardId'): TestData(), + field_id('Query', 'getMonitoringVPCConnectionId'): TestData(), + field_id('Query', 'getOmicsWorkflow'): TestData(), + field_id('Query', 'getOrganization'): TestData(), + field_id('Query', 'getPivotRoleExternalId'): TestData(), + field_id('Query', 'getPivotRoleName'): TestData(), + field_id('Query', 'getPivotRolePresignedUrl'): TestData(), + field_id('Query', 'getPlatformAuthorSession'): TestData(), + field_id('Query', 'getPlatformReaderSession'): TestData(), + field_id('Query', 'getReaderSession'): TestData(), + field_id('Query', 'getRedshiftDataset'): TestData(), + field_id('Query', 'getRedshiftDatasetTable'): TestData(), + field_id('Query', 'getRedshiftDatasetTableColumns'): TestData(), + field_id('Query', 'getS3ConsumptionData'): TestData(), + field_id('Query', 'getSagemakerNotebook'): TestData(), + field_id('Query', 'getSagemakerNotebookPresignedUrl'): TestData(tenant_perm=MANAGE_NOTEBOOKS), + field_id('Query', 'getSagemakerStudioUser'): TestData(), + field_id('Query', 'getSagemakerStudioUserPresignedUrl'): TestData(tenant_perm=MANAGE_SGMSTUDIO_USERS), + field_id('Query', 'getShare'): TestData(), + field_id('Query', 'getShareItemDataFilters'): TestData(), + field_id('Query', 'getShareLogs'): TestData(), + field_id('Query', 'getShareObject'): TestData(), + field_id('Query', 'getShareRequestsFromMe'): TestData(), + field_id('Query', 'getShareRequestsToMe'): TestData(), + field_id('Query', 'getSharedDatasetTables'): TestData(), + field_id('Query', 'getStack'): TestData(), + field_id('Query', 'getStackLogs'): TestData(), + field_id('Query', 'getTrustAccount'): TestData(), + field_id('Query', 'getVote'): TestData(), + field_id('Query', 'getWorksheet'): TestData(), + field_id('Query', 'listAllConsumptionRoles'): TestData(), + field_id('Query', 'listAllEnvironmentConsumptionRoles'): TestData(), + field_id('Query', 'listAllEnvironmentGroups'): TestData(), + field_id('Query', 'listAllGroups'): TestData(), + field_id('Query', 'listAttachedMetadataForms'): TestData(), + field_id('Query', 'listConnectionGroupNoPermissions'): TestData(), + field_id('Query', 'listConnectionGroupPermissions'): TestData(), + field_id('Query', 'listDashboardShares'): TestData(), + field_id('Query', 'listDataPipelines'): TestData(), + field_id('Query', 'listDatasetTableColumns'): TestData(), + field_id('Query', 'listDatasetTableProfilingRuns'): TestData(), + field_id('Query', 'listDatasetTables'): TestData(), + field_id('Query', 'listDatasets'): TestData(), + field_id('Query', 'listDatasetsCreatedInEnvironment'): TestData(), + field_id('Query', 'listEntityMetadataForms'): TestData(), + field_id('Query', 'listEnvironmentConsumptionRoles'): TestData(), + field_id('Query', 'listEnvironmentGroupInvitationPermissions'): TestData(), + field_id('Query', 'listEnvironmentGroups'): TestData(), + field_id('Query', 'listEnvironmentInvitedGroups'): TestData(), + field_id('Query', 'listEnvironmentNetworks'): TestData(), + field_id('Query', 'listEnvironmentRedshiftConnections'): TestData(), + field_id('Query', 'listEnvironments'): TestData(), + field_id('Query', 'listGlossaries'): TestData(), + field_id('Query', 'listGroups'): TestData(), + field_id('Query', 'listInviteOrganizationPermissionsWithDescriptions'): TestData(), + field_id('Query', 'listKeyValueTags'): TestData(), + field_id('Query', 'listMetadataFormVersions'): TestData(), + field_id('Query', 'listNotifications'): TestData(), + field_id('Query', 'listOmicsRuns'): TestData(), + field_id('Query', 'listOmicsWorkflows'): TestData(), + field_id('Query', 'listOrganizationGroupPermissions'): TestData(), + field_id('Query', 'listOrganizationGroups'): TestData(), + field_id('Query', 'listOrganizations'): TestData(), + field_id('Query', 'listOwnedDatasets'): TestData(), + field_id('Query', 'listRedshiftConnectionSchemas'): TestData(), + field_id('Query', 'listRedshiftDatasetTables'): TestData(), + field_id('Query', 'listRedshiftSchemaDatasetTables'): TestData(), + field_id('Query', 'listRedshiftSchemaTables'): TestData(), + field_id('Query', 'listS3DatasetsOwnedByEnvGroup'): TestData(), + field_id('Query', 'listS3DatasetsSharedWithEnvGroup'): TestData(), + field_id('Query', 'listSagemakerNotebooks'): TestData(), + field_id('Query', 'listSagemakerStudioUsers'): TestData(), + field_id('Query', 'listSharedDatasetTableColumns'): TestData(), + field_id('Query', 'listTableDataFilters'): TestData(), + field_id('Query', 'listTableDataFiltersByAttached'): TestData(), + field_id('Query', 'listTenantGroups'): TestData(), + field_id('Query', 'listTenantPermissions'): TestData(), + field_id('Query', 'listUserMetadataForms'): TestData(), + field_id('Query', 'listUsersForGroup'): TestData(), + field_id('Query', 'listValidEnvironments'): TestData(), + field_id('Query', 'listWorksheets'): TestData(), + field_id('Query', 'previewTable'): TestData(), + field_id('Query', 'queryEnums'): TestData(), + field_id('Query', 'runAthenaSqlQuery'): TestData(), + field_id('Query', 'searchDashboards'): TestData(), + field_id('Query', 'searchEnvironmentDataItems'): TestData(), + field_id('Query', 'searchGlossary'): TestData(), # Admin actions - field_id('Mutation', 'updateGroupTenantPermissions'): IgnoreReason.ADMIN.value, - field_id('Mutation', 'updateSSMParameter'): IgnoreReason.ADMIN.value, - field_id('Mutation', 'createQuicksightDataSourceSet'): IgnoreReason.ADMIN.value, - field_id('Mutation', 'startMaintenanceWindow'): IgnoreReason.ADMIN.value, - field_id('Mutation', 'stopMaintenanceWindow'): IgnoreReason.ADMIN.value, - field_id('Mutation', 'startReindexCatalog'): IgnoreReason.ADMIN.value, + field_id('Mutation', 'updateGroupTenantPermissions'): TestData(tenant_ignore=IgnoreReason.ADMIN), + field_id('Mutation', 'updateSSMParameter'): TestData(tenant_ignore=IgnoreReason.ADMIN), + field_id('Mutation', 'createQuicksightDataSourceSet'): TestData(tenant_ignore=IgnoreReason.ADMIN), + field_id('Mutation', 'startMaintenanceWindow'): TestData(tenant_ignore=IgnoreReason.ADMIN), + field_id('Mutation', 'stopMaintenanceWindow'): TestData(tenant_ignore=IgnoreReason.ADMIN), + field_id('Mutation', 'startReindexCatalog'): TestData(tenant_ignore=IgnoreReason.ADMIN), # Support-related actions - field_id('Mutation', 'markNotificationAsRead'): IgnoreReason.SUPPORT.value, - field_id('Mutation', 'deleteNotification'): IgnoreReason.SUPPORT.value, - field_id('Mutation', 'postFeedMessage'): IgnoreReason.FEED.value, - field_id('Mutation', 'upVote'): IgnoreReason.VOTES.value, + field_id('Mutation', 'markNotificationAsRead'): TestData(tenant_ignore=IgnoreReason.SUPPORT), + field_id('Mutation', 'deleteNotification'): TestData(tenant_ignore=IgnoreReason.SUPPORT), + field_id('Mutation', 'postFeedMessage'): TestData(tenant_ignore=IgnoreReason.FEED), + field_id('Mutation', 'upVote'): TestData(tenant_ignore=IgnoreReason.VOTES), # Backport-related actions - field_id('Mutation', 'createAttachedMetadataForm'): IgnoreReason.BACKPORT.value, - field_id('Mutation', 'deleteAttachedMetadataForm'): IgnoreReason.BACKPORT.value, - field_id('Mutation', 'createRedshiftConnection'): IgnoreReason.BACKPORT.value, - field_id('Mutation', 'deleteRedshiftConnection'): IgnoreReason.BACKPORT.value, - field_id('Mutation', 'addConnectionGroupPermission'): IgnoreReason.BACKPORT.value, - field_id('Mutation', 'deleteConnectionGroupPermission'): IgnoreReason.BACKPORT.value, + field_id('Mutation', 'createAttachedMetadataForm'): TestData(tenant_ignore=IgnoreReason.BACKPORT), + field_id('Mutation', 'deleteAttachedMetadataForm'): TestData(tenant_ignore=IgnoreReason.BACKPORT), + field_id('Mutation', 'createRedshiftConnection'): TestData(tenant_ignore=IgnoreReason.BACKPORT), + field_id('Mutation', 'deleteRedshiftConnection'): TestData(tenant_ignore=IgnoreReason.BACKPORT), + field_id('Mutation', 'addConnectionGroupPermission'): TestData(tenant_ignore=IgnoreReason.BACKPORT), + field_id('Mutation', 'deleteConnectionGroupPermission'): TestData(tenant_ignore=IgnoreReason.BACKPORT), } @@ -338,10 +350,11 @@ def test_unauthorized_tenant_permissions( groupNoTenantPermissions, ): fid = request.node.callspec.id - expected_perm = TOP_LEVEL_QUERIES.get(fid, 'NON_EXISTENT_PERM') + tdata = TENANT_CHECKS[fid] msg = f'{fid} -> {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' - if SKIP_MARK in expected_perm: - pytest.skip(msg + f' Reason: {expected_perm}') + expected_perm = tdata.tenant_perm + if not expected_perm: + pytest.skip(msg + f' Reason: {tdata.tenant_ignore.value}') logging.info(msg) assert_that(field.resolver).is_not_none() From ec6beb05dbc842070e3aaeb48d31f038cc460b6b Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Fri, 29 Nov 2024 18:09:17 +0200 Subject: [PATCH 22/47] generalise resource/tenant tests --- tests/test_tenant_unauthorized.py | 358 ++++++++++++++---------------- 1 file changed, 172 insertions(+), 186 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index aed638c44..9eab15b8b 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -34,20 +34,17 @@ def resolver_id(type_name, field_name): return f'{type_name}_{field_name}' -SKIP_MARK = '@SKIP@' - - class IgnoreReason(Enum): - ADMIN = f'{SKIP_MARK} admin action. No need for tenant permission check' - SUPPORT = f'{SKIP_MARK} permissions do not apply to support notifications' - FEED = f'{SKIP_MARK} permissions do not apply to support feed messages' - VOTES = f'{SKIP_MARK} permissions do not apply to support votes' - BACKPORT = f'{SKIP_MARK} outside of this PR to be able to backport to v2.6.2' - INTRAMODULE = f'{SKIP_MARK} returns intra-module data' - PERMCHECK = f'{SKIP_MARK} checks user permissions for a particular feature' - CATALOG = f'{SKIP_MARK} catalog resources are public by design' - SIMPLIFIED = f'{SKIP_MARK} simplified response' - NOTIMPLEMENTED = f'{SKIP_MARK} not implemented' + ADMIN = 'admin action. No need for tenant permission check' + SUPPORT = 'permissions do not apply to support notifications' + FEED = 'permissions do not apply to support feed messages' + VOTES = 'permissions do not apply to support votes' + BACKPORT = 'outside of this PR to be able to backport to v2.6.2' + INTRAMODULE = 'returns intra-module data' + PERMCHECK = 'checks user permissions for a particular feature' + CATALOG = 'catalog resources are public by design' + SIMPLIFIED = 'simplified response' + NOTREQUIRED = 'permission check is not required' def field_id(type_name: str, field_name: str) -> str: @@ -59,14 +56,83 @@ def field_id(type_name: str, field_name: str) -> str: @dataclass class TestData: - resource_ignore: IgnoreReason = IgnoreReason.NOTIMPLEMENTED + resource_ignore: IgnoreReason = IgnoreReason.NOTREQUIRED resource_perm: str = None - tenant_ignore: IgnoreReason = IgnoreReason.NOTIMPLEMENTED + tenant_ignore: IgnoreReason = IgnoreReason.NOTREQUIRED tenant_perm: str = None -TENANT_CHECKS: Mapping[str, TestData] = { +EXPECTED_RESOLVERS: Mapping[str, TestData] = { + field_id('AttachedMetadataForm', 'entityName'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('AttachedMetadataForm', 'fields'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('AttachedMetadataForm', 'metadataForm'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('AttachedMetadataFormField', 'field'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('AttachedMetadataFormField', 'hasTenantPermissions'): TestData(resource_ignore=IgnoreReason.PERMCHECK), + field_id('Category', 'associations'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Category', 'categories'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Category', 'children'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Category', 'stats'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Category', 'terms'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('ConsumptionRole', 'managedPolicies'): TestData(resource_perm=GET_ENVIRONMENT), + field_id('Dashboard', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), + field_id('Dashboard', 'terms'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('Dashboard', 'upvotes'): TestData(resource_ignore=IgnoreReason.VOTES), + field_id('Dashboard', 'userRoleForDashboard'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('DataPipeline', 'cloneUrlHttp'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('DataPipeline', 'developmentEnvironments'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('DataPipeline', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), + field_id('DataPipeline', 'organization'): TestData(resource_perm=GET_ORGANIZATION), + field_id('DataPipeline', 'stack'): TestData(resource_perm=GET_PIPELINE), + field_id('DataPipeline', 'userRoleForPipeline'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Dataset', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), + field_id('Dataset', 'locations'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Dataset', 'owners'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Dataset', 'stack'): TestData(resource_perm=GET_DATASET), + field_id('Dataset', 'statistics'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Dataset', 'stewards'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Dataset', 'tables'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Dataset', 'terms'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('Dataset', 'userRoleForDataset'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('DatasetBase', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), + field_id('DatasetBase', 'owners'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('DatasetBase', 'stack'): TestData(resource_perm=GET_DATASET), + field_id('DatasetBase', 'stewards'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('DatasetBase', 'userRoleForDataset'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('DatasetProfilingRun', 'dataset'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('DatasetProfilingRun', 'results'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('DatasetProfilingRun', 'status'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('DatasetStorageLocation', 'dataset'): TestData(resource_perm=GET_DATASET), + field_id('DatasetStorageLocation', 'terms'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('DatasetTable', 'GlueTableProperties'): TestData(resource_perm=GET_DATASET_TABLE), + field_id('DatasetTable', 'columns'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('DatasetTable', 'dataset'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('DatasetTable', 'terms'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('DatasetTableColumn', 'terms'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('Environment', 'networks'): TestData(resource_perm=GET_NETWORK), + field_id('Environment', 'organization'): TestData(resource_ignore=IgnoreReason.SIMPLIFIED), + field_id('Environment', 'parameters'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Environment', 'stack'): TestData(resource_perm=GET_ENVIRONMENT), + field_id('Environment', 'userRoleInEnvironment'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('EnvironmentSimplified', 'networks'): TestData(resource_perm=GET_NETWORK), + field_id('EnvironmentSimplified', 'organization'): TestData(resource_ignore=IgnoreReason.SIMPLIFIED), + field_id('Feed', 'messages'): TestData(resource_ignore=IgnoreReason.FEED), + field_id('Glossary', 'associations'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('Glossary', 'categories'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('Glossary', 'children'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('Glossary', 'stats'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('Glossary', 'tree'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('Glossary', 'userRoleForGlossary'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('GlossaryTermLink', 'target'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('GlossaryTermLink', 'term'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('Group', 'environmentPermissions'): TestData(resource_ignore=IgnoreReason.PERMCHECK), + field_id('Group', 'tenantPermissions'): TestData(resource_ignore=IgnoreReason.PERMCHECK), + field_id('MetadataForm', 'fields'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('MetadataForm', 'homeEntityName'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('MetadataForm', 'userRole'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('MetadataFormField', 'glossaryNodeName'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('MetadataFormSearchResult', 'hasTenantPermissions'): TestData(resource_ignore=IgnoreReason.PERMCHECK), field_id('Mutation', 'DisableDataSubscriptions'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), + field_id('Mutation', 'addConnectionGroupPermission'): TestData(tenant_ignore=IgnoreReason.BACKPORT), field_id('Mutation', 'addConsumptionRoleToEnvironment'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), field_id('Mutation', 'addRedshiftDatasetTables'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), field_id('Mutation', 'addSharedItem'): TestData(tenant_perm=MANAGE_SHARES), @@ -77,6 +143,7 @@ class TestData: field_id('Mutation', 'archiveOrganization'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), field_id('Mutation', 'batchMetadataFormFieldUpdates'): TestData(tenant_perm=MANAGE_METADATA_FORMS), field_id('Mutation', 'cancelShareExtension'): TestData(tenant_perm=MANAGE_SHARES), + field_id('Mutation', 'createAttachedMetadataForm'): TestData(tenant_ignore=IgnoreReason.BACKPORT), field_id('Mutation', 'createCategory'): TestData(tenant_perm=MANAGE_GLOSSARIES), field_id('Mutation', 'createDataPipeline'): TestData(tenant_perm=MANAGE_PIPELINES), field_id('Mutation', 'createDataPipelineEnvironment'): TestData(tenant_perm=MANAGE_PIPELINES), @@ -90,13 +157,17 @@ class TestData: field_id('Mutation', 'createNetwork'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), field_id('Mutation', 'createOmicsRun'): TestData(tenant_perm=MANAGE_OMICS_RUNS), field_id('Mutation', 'createOrganization'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), + field_id('Mutation', 'createQuicksightDataSourceSet'): TestData(tenant_ignore=IgnoreReason.ADMIN), + field_id('Mutation', 'createRedshiftConnection'): TestData(tenant_ignore=IgnoreReason.BACKPORT), field_id('Mutation', 'createSagemakerNotebook'): TestData(tenant_perm=MANAGE_NOTEBOOKS), field_id('Mutation', 'createSagemakerStudioUser'): TestData(tenant_perm=MANAGE_SGMSTUDIO_USERS), field_id('Mutation', 'createShareObject'): TestData(tenant_perm=MANAGE_SHARES), field_id('Mutation', 'createTableDataFilter'): TestData(tenant_perm=MANAGE_DATASETS), field_id('Mutation', 'createTerm'): TestData(tenant_perm=MANAGE_GLOSSARIES), field_id('Mutation', 'createWorksheet'): TestData(tenant_perm=MANAGE_WORKSHEETS), + field_id('Mutation', 'deleteAttachedMetadataForm'): TestData(tenant_ignore=IgnoreReason.BACKPORT), field_id('Mutation', 'deleteCategory'): TestData(tenant_perm=MANAGE_GLOSSARIES), + field_id('Mutation', 'deleteConnectionGroupPermission'): TestData(tenant_ignore=IgnoreReason.BACKPORT), field_id('Mutation', 'deleteDashboard'): TestData(tenant_perm=MANAGE_DASHBOARDS), field_id('Mutation', 'deleteDataPipeline'): TestData(tenant_perm=MANAGE_PIPELINES), field_id('Mutation', 'deleteDataPipelineEnvironment'): TestData(tenant_perm=MANAGE_PIPELINES), @@ -109,7 +180,9 @@ class TestData: field_id('Mutation', 'deleteMetadataFormField'): TestData(tenant_perm=MANAGE_METADATA_FORMS), field_id('Mutation', 'deleteMetadataFormVersion'): TestData(tenant_perm=MANAGE_METADATA_FORMS), field_id('Mutation', 'deleteNetwork'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), + field_id('Mutation', 'deleteNotification'): TestData(tenant_ignore=IgnoreReason.SUPPORT), field_id('Mutation', 'deleteOmicsRun'): TestData(tenant_perm=MANAGE_OMICS_RUNS), + field_id('Mutation', 'deleteRedshiftConnection'): TestData(tenant_ignore=IgnoreReason.BACKPORT), field_id('Mutation', 'deleteRedshiftDataset'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), field_id('Mutation', 'deleteRedshiftDatasetTable'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), field_id('Mutation', 'deleteSagemakerNotebook'): TestData(tenant_perm=MANAGE_NOTEBOOKS), @@ -126,6 +199,8 @@ class TestData: field_id('Mutation', 'importRedshiftDataset'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), field_id('Mutation', 'inviteGroupOnEnvironment'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), field_id('Mutation', 'inviteGroupToOrganization'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), + field_id('Mutation', 'markNotificationAsRead'): TestData(tenant_ignore=IgnoreReason.SUPPORT), + field_id('Mutation', 'postFeedMessage'): TestData(tenant_ignore=IgnoreReason.FEED), field_id('Mutation', 'reApplyItemsShareObject'): TestData(tenant_perm=MANAGE_SHARES), field_id('Mutation', 'reApplyShareObjectItemsOnDataset'): TestData(tenant_perm=MANAGE_DATASETS), field_id('Mutation', 'rejectDashboardShare'): TestData(tenant_perm=MANAGE_DASHBOARDS), @@ -139,12 +214,16 @@ class TestData: field_id('Mutation', 'revokeItemsShareObject'): TestData(tenant_perm=MANAGE_SHARES), field_id('Mutation', 'startDatasetProfilingRun'): TestData(tenant_perm=MANAGE_DATASETS), field_id('Mutation', 'startGlueCrawler'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'startMaintenanceWindow'): TestData(tenant_ignore=IgnoreReason.ADMIN), + field_id('Mutation', 'startReindexCatalog'): TestData(tenant_ignore=IgnoreReason.ADMIN), field_id('Mutation', 'startSagemakerNotebook'): TestData(tenant_perm=MANAGE_NOTEBOOKS), + field_id('Mutation', 'stopMaintenanceWindow'): TestData(tenant_ignore=IgnoreReason.ADMIN), field_id('Mutation', 'stopSagemakerNotebook'): TestData(tenant_perm=MANAGE_NOTEBOOKS), field_id('Mutation', 'submitShareExtension'): TestData(tenant_perm=MANAGE_SHARES), field_id('Mutation', 'submitShareObject'): TestData(tenant_perm=MANAGE_SHARES), field_id('Mutation', 'syncDatasetTableColumns'): TestData(tenant_perm=MANAGE_DATASETS), field_id('Mutation', 'syncTables'): TestData(tenant_perm=MANAGE_DATASETS), + field_id('Mutation', 'upVote'): TestData(tenant_ignore=IgnoreReason.VOTES), field_id('Mutation', 'updateCategory'): TestData(tenant_perm=MANAGE_GLOSSARIES), field_id('Mutation', 'updateConsumptionRole'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), field_id('Mutation', 'updateDashboard'): TestData(tenant_perm=MANAGE_DASHBOARDS), @@ -157,11 +236,13 @@ class TestData: field_id('Mutation', 'updateEnvironment'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), field_id('Mutation', 'updateGlossary'): TestData(tenant_perm=MANAGE_GLOSSARIES), field_id('Mutation', 'updateGroupEnvironmentPermissions'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), + field_id('Mutation', 'updateGroupTenantPermissions'): TestData(tenant_ignore=IgnoreReason.ADMIN), field_id('Mutation', 'updateKeyValueTags'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), field_id('Mutation', 'updateOrganization'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), field_id('Mutation', 'updateOrganizationGroup'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), field_id('Mutation', 'updateRedshiftDataset'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), field_id('Mutation', 'updateRedshiftDatasetTable'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), + field_id('Mutation', 'updateSSMParameter'): TestData(tenant_ignore=IgnoreReason.ADMIN), field_id('Mutation', 'updateShareExpirationPeriod'): TestData(tenant_perm=MANAGE_SHARES), field_id('Mutation', 'updateShareExtensionReason'): TestData(tenant_perm=MANAGE_SHARES), field_id('Mutation', 'updateShareItemFilters'): TestData(tenant_perm=MANAGE_SHARES), @@ -172,6 +253,14 @@ class TestData: field_id('Mutation', 'updateWorksheet'): TestData(tenant_perm=MANAGE_WORKSHEETS), field_id('Mutation', 'verifyDatasetShareObjects'): TestData(tenant_perm=MANAGE_DATASETS), field_id('Mutation', 'verifyItemsShareObject'): TestData(tenant_perm=MANAGE_SHARES), + field_id('OmicsRun', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), + field_id('OmicsRun', 'organization'): TestData(resource_perm=GET_ORGANIZATION), + field_id('OmicsRun', 'status'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('OmicsRun', 'workflow'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Organization', 'environments'): TestData(resource_perm=GET_ORGANIZATION), + field_id('Organization', 'stats'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Organization', 'userRoleInOrganization'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Permission', 'type'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('Query', 'countDeletedNotifications'): TestData(), field_id('Query', 'countReadNotifications'): TestData(), field_id('Query', 'countUnreadNotifications'): TestData(), @@ -219,7 +308,6 @@ class TestData: field_id('Query', 'getSagemakerNotebookPresignedUrl'): TestData(tenant_perm=MANAGE_NOTEBOOKS), field_id('Query', 'getSagemakerStudioUser'): TestData(), field_id('Query', 'getSagemakerStudioUserPresignedUrl'): TestData(tenant_perm=MANAGE_SGMSTUDIO_USERS), - field_id('Query', 'getShare'): TestData(), field_id('Query', 'getShareItemDataFilters'): TestData(), field_id('Query', 'getShareLogs'): TestData(), field_id('Query', 'getShareObject'): TestData(), @@ -288,27 +376,60 @@ class TestData: field_id('Query', 'searchDashboards'): TestData(), field_id('Query', 'searchEnvironmentDataItems'): TestData(), field_id('Query', 'searchGlossary'): TestData(), - # Admin actions - field_id('Mutation', 'updateGroupTenantPermissions'): TestData(tenant_ignore=IgnoreReason.ADMIN), - field_id('Mutation', 'updateSSMParameter'): TestData(tenant_ignore=IgnoreReason.ADMIN), - field_id('Mutation', 'createQuicksightDataSourceSet'): TestData(tenant_ignore=IgnoreReason.ADMIN), - field_id('Mutation', 'startMaintenanceWindow'): TestData(tenant_ignore=IgnoreReason.ADMIN), - field_id('Mutation', 'stopMaintenanceWindow'): TestData(tenant_ignore=IgnoreReason.ADMIN), - field_id('Mutation', 'startReindexCatalog'): TestData(tenant_ignore=IgnoreReason.ADMIN), - # Support-related actions - field_id('Mutation', 'markNotificationAsRead'): TestData(tenant_ignore=IgnoreReason.SUPPORT), - field_id('Mutation', 'deleteNotification'): TestData(tenant_ignore=IgnoreReason.SUPPORT), - field_id('Mutation', 'postFeedMessage'): TestData(tenant_ignore=IgnoreReason.FEED), - field_id('Mutation', 'upVote'): TestData(tenant_ignore=IgnoreReason.VOTES), - # Backport-related actions - field_id('Mutation', 'createAttachedMetadataForm'): TestData(tenant_ignore=IgnoreReason.BACKPORT), - field_id('Mutation', 'deleteAttachedMetadataForm'): TestData(tenant_ignore=IgnoreReason.BACKPORT), - field_id('Mutation', 'createRedshiftConnection'): TestData(tenant_ignore=IgnoreReason.BACKPORT), - field_id('Mutation', 'deleteRedshiftConnection'): TestData(tenant_ignore=IgnoreReason.BACKPORT), - field_id('Mutation', 'addConnectionGroupPermission'): TestData(tenant_ignore=IgnoreReason.BACKPORT), - field_id('Mutation', 'deleteConnectionGroupPermission'): TestData(tenant_ignore=IgnoreReason.BACKPORT), + field_id('RedshiftDataset', 'connection'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('RedshiftDataset', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), + field_id('RedshiftDataset', 'owners'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('RedshiftDataset', 'stewards'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('RedshiftDataset', 'terms'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('RedshiftDataset', 'upvotes'): TestData(resource_ignore=IgnoreReason.VOTES), + field_id('RedshiftDataset', 'userRoleForDataset'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('RedshiftDatasetTable', 'dataset'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('RedshiftDatasetTable', 'terms'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('SagemakerNotebook', 'NotebookInstanceStatus'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('SagemakerNotebook', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), + field_id('SagemakerNotebook', 'organization'): TestData(resource_perm=GET_ORGANIZATION), + field_id('SagemakerNotebook', 'stack'): TestData(resource_perm=GET_NOTEBOOK), + field_id('SagemakerNotebook', 'userRoleForNotebook'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('SagemakerStudioDomain', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), + field_id('SagemakerStudioUser', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), + field_id('SagemakerStudioUser', 'organization'): TestData(resource_perm=GET_ORGANIZATION), + field_id('SagemakerStudioUser', 'sagemakerStudioUserApps'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('SagemakerStudioUser', 'sagemakerStudioUserStatus'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('SagemakerStudioUser', 'stack'): TestData(resource_perm=GET_SGMSTUDIO_USER), + field_id('SagemakerStudioUser', 'userRoleForSagemakerStudioUser'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE + ), + field_id('ShareObject', 'canViewLogs'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('ShareObject', 'dataset'): TestData(resource_ignore=IgnoreReason.SIMPLIFIED), + field_id('ShareObject', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), + field_id('ShareObject', 'existingSharedItems'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('ShareObject', 'group'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('ShareObject', 'items'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('ShareObject', 'principal'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('ShareObject', 'statistics'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('ShareObject', 'userRoleForShareObject'): TestData(resource_ignore=IgnoreReason.PERMCHECK), + field_id('SharedDatabaseTableItem', 'sharedGlueDatabaseName'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Stack', 'EcsTaskId'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Stack', 'canViewLogs'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Stack', 'error'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Stack', 'events'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Stack', 'link'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Stack', 'outputs'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Stack', 'resources'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Term', 'associations'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Term', 'children'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Term', 'glossary'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Term', 'stats'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('Worksheet', 'userRoleForWorksheet'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), } +# ensure that all EXPECTED_RESOURCES_PERMS have a corresponding query (to avoid stale entries) and vice versa +assert_that([field_id(res[0].name, res[1].name) for res in ALL_RESOLVERS]).described_as( + 'stale or missing EXPECTED_RESOURCE_PERMS detected' +).contains_only(*EXPECTED_RESOLVERS.keys()) + +ALL_PARAMS = [pytest.param(_type, field, id=field_id(_type.name, field.name)) for _type, field in ALL_RESOLVERS] + @pytest.fixture(scope='function') def mock_input_validation(mocker): @@ -328,15 +449,11 @@ def mock_input_validation(mocker): mocker.patch('dataall.modules.shares_base.api.resolvers.RequestValidator', MagicMock()) -@pytest.mark.parametrize( - '_type,field', - [ - pytest.param(_type, field, id=field_id(_type.name, field.name)) - for _type, field in ALL_RESOLVERS - if _type.name in ['Query', 'Mutation'] - ], +@pytest.mark.parametrize('_type,field', ALL_PARAMS) +@patch( + 'dataall.core.permissions.services.tenant_policy_service.TenantPolicyService.check_user_tenant_permission', + wraps=TenantPolicyService.check_user_tenant_permission, ) -@patch('dataall.core.permissions.services.tenant_policy_service.TenantPolicyService.check_user_tenant_permission', wraps=TenantPolicyService.check_user_tenant_permission) @patch('dataall.base.context._request_storage') def test_unauthorized_tenant_permissions( mock_local, @@ -350,7 +467,7 @@ def test_unauthorized_tenant_permissions( groupNoTenantPermissions, ): fid = request.node.callspec.id - tdata = TENANT_CHECKS[fid] + tdata = EXPECTED_RESOLVERS[fid] msg = f'{fid} -> {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' expected_perm = tdata.tenant_perm if not expected_perm: @@ -360,165 +477,34 @@ def test_unauthorized_tenant_permissions( assert_that(field.resolver).is_not_none() groups = [groupNoTenantPermissions.groupUri] username = userNoTenantPermissions.username - mock_local.context = RequestContext( - db, username, groups, userNoTenantPermissions - ) + mock_local.context = RequestContext(db, username, groups, userNoTenantPermissions) # Mocking arguments iargs = {arg: MagicMock() for arg in inspect.signature(field.resolver).parameters.keys()} # Assert Unauthorized exception is raised assert_that(field.resolver).raises(TenantUnauthorized).when_called_with(**iargs).contains('UnauthorizedOperation') - spy_check.assert_called_once_with(session=ANY, username=username, groups=groups, tenant_name=ANY, permission_name=expected_perm) - - -EXPECTED_RESOURCE_PERMS = { - field_id('AttachedMetadataFormField', 'field'): IgnoreReason.INTRAMODULE.value, - field_id('AttachedMetadataFormField', 'hasTenantPermissions'): IgnoreReason.PERMCHECK.value, - field_id('AttachedMetadataForm', 'entityName'): IgnoreReason.INTRAMODULE.value, - field_id('AttachedMetadataForm', 'fields'): IgnoreReason.INTRAMODULE.value, - field_id('AttachedMetadataForm', 'metadataForm'): IgnoreReason.INTRAMODULE.value, - field_id('Category', 'associations'): IgnoreReason.INTRAMODULE.value, - field_id('Category', 'categories'): IgnoreReason.INTRAMODULE.value, - field_id('Category', 'children'): IgnoreReason.INTRAMODULE.value, - field_id('Category', 'stats'): IgnoreReason.INTRAMODULE.value, - field_id('Category', 'terms'): IgnoreReason.INTRAMODULE.value, - field_id('ConsumptionRole', 'managedPolicies'): GET_ENVIRONMENT, - field_id('Dashboard', 'environment'): GET_ENVIRONMENT, - field_id('Dashboard', 'terms'): IgnoreReason.CATALOG.value, - field_id('Dashboard', 'upvotes'): IgnoreReason.VOTES.value, - field_id('Dashboard', 'userRoleForDashboard'): IgnoreReason.INTRAMODULE.value, - field_id('DataPipeline', 'cloneUrlHttp'): IgnoreReason.INTRAMODULE.value, - field_id('DataPipeline', 'developmentEnvironments'): IgnoreReason.INTRAMODULE.value, - field_id('DataPipeline', 'environment'): GET_ENVIRONMENT, - field_id('DataPipeline', 'organization'): GET_ORGANIZATION, - field_id('DataPipeline', 'stack'): GET_PIPELINE, - field_id('DataPipeline', 'userRoleForPipeline'): IgnoreReason.INTRAMODULE.value, - field_id('DatasetBase', 'environment'): GET_ENVIRONMENT, - field_id('DatasetBase', 'owners'): IgnoreReason.INTRAMODULE.value, - field_id('DatasetBase', 'stack'): GET_DATASET, - field_id('DatasetBase', 'stewards'): IgnoreReason.INTRAMODULE.value, - field_id('DatasetBase', 'userRoleForDataset'): IgnoreReason.INTRAMODULE.value, - field_id('DatasetProfilingRun', 'dataset'): IgnoreReason.INTRAMODULE.value, - field_id('DatasetProfilingRun', 'results'): IgnoreReason.INTRAMODULE.value, - field_id('DatasetProfilingRun', 'status'): IgnoreReason.INTRAMODULE.value, - field_id('DatasetStorageLocation', 'dataset'): GET_DATASET, - field_id('DatasetStorageLocation', 'terms'): IgnoreReason.CATALOG.value, - field_id('DatasetTableColumn', 'terms'): IgnoreReason.CATALOG.value, - field_id('DatasetTable', 'GlueTableProperties'): GET_DATASET_TABLE, - field_id('DatasetTable', 'columns'): IgnoreReason.INTRAMODULE.value, - field_id('DatasetTable', 'dataset'): IgnoreReason.INTRAMODULE.value, - field_id('DatasetTable', 'terms'): IgnoreReason.CATALOG.value, - field_id('Dataset', 'environment'): GET_ENVIRONMENT, - field_id('Dataset', 'locations'): IgnoreReason.INTRAMODULE.value, - field_id('Dataset', 'owners'): IgnoreReason.INTRAMODULE.value, - field_id('Dataset', 'stack'): GET_DATASET, - field_id('Dataset', 'statistics'): IgnoreReason.INTRAMODULE.value, - field_id('Dataset', 'stewards'): IgnoreReason.INTRAMODULE.value, - field_id('Dataset', 'tables'): IgnoreReason.INTRAMODULE.value, - field_id('Dataset', 'terms'): IgnoreReason.CATALOG.value, - field_id('Dataset', 'userRoleForDataset'): IgnoreReason.INTRAMODULE.value, - field_id('EnvironmentSimplified', 'networks'): GET_NETWORK, - field_id('EnvironmentSimplified', 'organization'): IgnoreReason.SIMPLIFIED.value, - field_id('Environment', 'networks'): GET_NETWORK, - field_id('Environment', 'organization'): IgnoreReason.SIMPLIFIED.value, - field_id('Environment', 'parameters'): IgnoreReason.INTRAMODULE.value, - field_id('Environment', 'stack'): GET_ENVIRONMENT, - field_id('Environment', 'userRoleInEnvironment'): IgnoreReason.INTRAMODULE.value, - field_id('Feed', 'messages'): IgnoreReason.FEED.value, - field_id('GlossaryTermLink', 'target'): IgnoreReason.CATALOG.value, - field_id('GlossaryTermLink', 'term'): IgnoreReason.CATALOG.value, - field_id('Glossary', 'associations'): IgnoreReason.CATALOG.value, - field_id('Glossary', 'categories'): IgnoreReason.CATALOG.value, - field_id('Glossary', 'children'): IgnoreReason.CATALOG.value, - field_id('Glossary', 'stats'): IgnoreReason.CATALOG.value, - field_id('Glossary', 'tree'): IgnoreReason.CATALOG.value, - field_id('Glossary', 'userRoleForGlossary'): IgnoreReason.CATALOG.value, - field_id('Group', 'environmentPermissions'): IgnoreReason.PERMCHECK.value, - field_id('Group', 'tenantPermissions'): IgnoreReason.PERMCHECK.value, - field_id('MetadataFormField', 'glossaryNodeName'): IgnoreReason.CATALOG.value, - field_id('MetadataFormSearchResult', 'hasTenantPermissions'): IgnoreReason.PERMCHECK.value, - field_id('MetadataForm', 'fields'): IgnoreReason.INTRAMODULE.value, - field_id('MetadataForm', 'homeEntityName'): IgnoreReason.INTRAMODULE.value, - field_id('MetadataForm', 'userRole'): IgnoreReason.INTRAMODULE.value, - field_id('OmicsRun', 'environment'): GET_ENVIRONMENT, - field_id('OmicsRun', 'organization'): GET_ORGANIZATION, - field_id('OmicsRun', 'status'): IgnoreReason.INTRAMODULE.value, - field_id('OmicsRun', 'workflow'): IgnoreReason.INTRAMODULE.value, - field_id('Organization', 'environments'): GET_ORGANIZATION, - field_id('Organization', 'stats'): IgnoreReason.INTRAMODULE.value, - field_id('Organization', 'userRoleInOrganization'): IgnoreReason.INTRAMODULE.value, - field_id('Permission', 'type'): IgnoreReason.INTRAMODULE.value, - field_id('RedshiftDataset', 'connection'): IgnoreReason.INTRAMODULE.value, - field_id('RedshiftDataset', 'environment'): GET_ENVIRONMENT, - field_id('RedshiftDataset', 'owners'): IgnoreReason.INTRAMODULE.value, - field_id('RedshiftDataset', 'stewards'): IgnoreReason.INTRAMODULE.value, - field_id('RedshiftDataset', 'terms'): IgnoreReason.CATALOG.value, - field_id('RedshiftDataset', 'upvotes'): IgnoreReason.VOTES.value, - field_id('RedshiftDataset', 'userRoleForDataset'): IgnoreReason.INTRAMODULE.value, - field_id('RedshiftDatasetTable', 'dataset'): IgnoreReason.INTRAMODULE.value, - field_id('RedshiftDatasetTable', 'terms'): IgnoreReason.CATALOG.value, - field_id('SagemakerNotebook', 'environment'): GET_ENVIRONMENT, - field_id('SagemakerNotebook', 'NotebookInstanceStatus'): IgnoreReason.INTRAMODULE.value, - field_id('SagemakerNotebook', 'organization'): GET_ORGANIZATION, - field_id('SagemakerNotebook', 'stack'): GET_NOTEBOOK, - field_id('SagemakerNotebook', 'userRoleForNotebook'): IgnoreReason.INTRAMODULE.value, - field_id('SagemakerStudioDomain', 'environment'): GET_ENVIRONMENT, - field_id('SagemakerStudioUser', 'environment'): GET_ENVIRONMENT, - field_id('SagemakerStudioUser', 'organization'): GET_ORGANIZATION, - field_id('SagemakerStudioUser', 'sagemakerStudioUserApps'): IgnoreReason.INTRAMODULE.value, - field_id('SagemakerStudioUser', 'sagemakerStudioUserStatus'): IgnoreReason.INTRAMODULE.value, - field_id('SagemakerStudioUser', 'stack'): GET_SGMSTUDIO_USER, - field_id('SagemakerStudioUser', 'userRoleForSagemakerStudioUser'): IgnoreReason.INTRAMODULE.value, - field_id('SharedDatabaseTableItem', 'sharedGlueDatabaseName'): IgnoreReason.INTRAMODULE.value, - field_id('ShareObject', 'canViewLogs'): IgnoreReason.INTRAMODULE.value, - field_id('ShareObject', 'dataset'): IgnoreReason.SIMPLIFIED.value, - field_id('ShareObject', 'environment'): GET_ENVIRONMENT, - field_id('ShareObject', 'existingSharedItems'): IgnoreReason.INTRAMODULE.value, - field_id('ShareObject', 'group'): IgnoreReason.INTRAMODULE.value, - field_id('ShareObject', 'items'): IgnoreReason.INTRAMODULE.value, - field_id('ShareObject', 'principal'): IgnoreReason.INTRAMODULE.value, - field_id('ShareObject', 'statistics'): IgnoreReason.INTRAMODULE.value, - field_id('ShareObject', 'userRoleForShareObject'): IgnoreReason.PERMCHECK.value, - field_id('Stack', 'canViewLogs'): IgnoreReason.INTRAMODULE.value, - field_id('Stack', 'EcsTaskId'): IgnoreReason.INTRAMODULE.value, - field_id('Stack', 'error'): IgnoreReason.INTRAMODULE.value, - field_id('Stack', 'events'): IgnoreReason.INTRAMODULE.value, - field_id('Stack', 'link'): IgnoreReason.INTRAMODULE.value, - field_id('Stack', 'outputs'): IgnoreReason.INTRAMODULE.value, - field_id('Stack', 'resources'): IgnoreReason.INTRAMODULE.value, - field_id('Term', 'associations'): IgnoreReason.INTRAMODULE.value, - field_id('Term', 'children'): IgnoreReason.INTRAMODULE.value, - field_id('Term', 'glossary'): IgnoreReason.INTRAMODULE.value, - field_id('Term', 'stats'): IgnoreReason.INTRAMODULE.value, - field_id('Worksheet', 'userRoleForWorksheet'): IgnoreReason.INTRAMODULE.value, -} - -PARAMS = [ - pytest.param(field, id=field_id(_type.name, field.name)) - for _type, field in ALL_RESOLVERS - if _type.name not in ['Query', 'Mutation'] # filter out top-level queries (don't print skip) -] -# ensure that all EXPECTED_RESOURCES_PERMS have a corresponding query (to avoid stale entries) and vice versa -assert_that(PARAMS).described_as('stale or missing EXPECTED_RESOURCE_PERMS detected').extracting(2).contains_only( - *EXPECTED_RESOURCE_PERMS.keys() -) + spy_check.assert_called_once_with( + session=ANY, username=username, groups=groups, tenant_name=ANY, permission_name=expected_perm + ) @patch('dataall.base.aws.sts.SessionHelper.remote_session') @patch('dataall.core.permissions.services.resource_policy_service.ResourcePolicyService.check_user_resource_permission') @patch('dataall.base.context._request_storage') -@pytest.mark.parametrize('field', PARAMS) +@pytest.mark.parametrize('_type,field', ALL_PARAMS) def test_unauthorized_resource_permissions( mock_local, mock_check, mock_session, + _type, field, request, ): fid = request.node.callspec.id - expected_perm = EXPECTED_RESOURCE_PERMS.get(fid, 'NON_EXISTENT_PERM') + tdata = EXPECTED_RESOLVERS[fid] msg = f'{fid} -> {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' - if SKIP_MARK in expected_perm: - pytest.skip(msg + f' Reason: {expected_perm}') + expected_perm = tdata.resource_perm + if not expected_perm: + pytest.skip(msg + f' Reason: {tdata.tenant_ignore.value}') logging.info(msg) assert_that(field.resolver).is_not_none() From 8681d7eb569f090ced581e0724600df5faf7c2da Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Mon, 2 Dec 2024 10:59:34 +0200 Subject: [PATCH 23/47] add test --- tests/test_tenant_unauthorized.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index 9eab15b8b..2443b9950 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -423,10 +423,15 @@ class TestData: field_id('Worksheet', 'userRoleForWorksheet'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), } -# ensure that all EXPECTED_RESOURCES_PERMS have a corresponding query (to avoid stale entries) and vice versa -assert_that([field_id(res[0].name, res[1].name) for res in ALL_RESOLVERS]).described_as( - 'stale or missing EXPECTED_RESOURCE_PERMS detected' -).contains_only(*EXPECTED_RESOLVERS.keys()) + +def test_all_resolvers_have_test_data(): + ''' + ensure that all EXPECTED_RESOURCES_PERMS have a corresponding query (to avoid stale entries) and vice versa + ''' + assert_that([field_id(res[0].name, res[1].name) for res in ALL_RESOLVERS]).described_as( + 'stale or missing EXPECTED_RESOURCE_PERMS detected' + ).contains_only(*EXPECTED_RESOLVERS.keys()) + ALL_PARAMS = [pytest.param(_type, field, id=field_id(_type.name, field.name)) for _type, field in ALL_RESOLVERS] From 96468350b23500889585781dbff51fda076a99ba Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Mon, 2 Dec 2024 11:04:24 +0200 Subject: [PATCH 24/47] add postinit --- tests/test_tenant_unauthorized.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index 2443b9950..436e1b853 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -61,6 +61,12 @@ class TestData: tenant_ignore: IgnoreReason = IgnoreReason.NOTREQUIRED tenant_perm: str = None + def __post_init__(self): + if not any([self.resource_perm, self.resource_ignore]): + raise ValueError("Either resource_perm or resource_ignore must be set") + if not any([self.tenant_perm, self.tenant_ignore]): + raise ValueError("Either tenant_perm or tenant_ignore must be set") + EXPECTED_RESOLVERS: Mapping[str, TestData] = { field_id('AttachedMetadataForm', 'entityName'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), From 64ac83ab59748338231864874093fddf3ba7c759 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Mon, 2 Dec 2024 11:04:48 +0200 Subject: [PATCH 25/47] rename to tenat --- tests/test_tenant_unauthorized.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index 436e1b853..a0775e1e4 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -35,7 +35,7 @@ def resolver_id(type_name, field_name): class IgnoreReason(Enum): - ADMIN = 'admin action. No need for tenant permission check' + TENANT = 'admin action. No need for tenant permission check' SUPPORT = 'permissions do not apply to support notifications' FEED = 'permissions do not apply to support feed messages' VOTES = 'permissions do not apply to support votes' @@ -163,7 +163,7 @@ def __post_init__(self): field_id('Mutation', 'createNetwork'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), field_id('Mutation', 'createOmicsRun'): TestData(tenant_perm=MANAGE_OMICS_RUNS), field_id('Mutation', 'createOrganization'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), - field_id('Mutation', 'createQuicksightDataSourceSet'): TestData(tenant_ignore=IgnoreReason.ADMIN), + field_id('Mutation', 'createQuicksightDataSourceSet'): TestData(tenant_ignore=IgnoreReason.TENANT), field_id('Mutation', 'createRedshiftConnection'): TestData(tenant_ignore=IgnoreReason.BACKPORT), field_id('Mutation', 'createSagemakerNotebook'): TestData(tenant_perm=MANAGE_NOTEBOOKS), field_id('Mutation', 'createSagemakerStudioUser'): TestData(tenant_perm=MANAGE_SGMSTUDIO_USERS), @@ -220,10 +220,10 @@ def __post_init__(self): field_id('Mutation', 'revokeItemsShareObject'): TestData(tenant_perm=MANAGE_SHARES), field_id('Mutation', 'startDatasetProfilingRun'): TestData(tenant_perm=MANAGE_DATASETS), field_id('Mutation', 'startGlueCrawler'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'startMaintenanceWindow'): TestData(tenant_ignore=IgnoreReason.ADMIN), - field_id('Mutation', 'startReindexCatalog'): TestData(tenant_ignore=IgnoreReason.ADMIN), + field_id('Mutation', 'startMaintenanceWindow'): TestData(tenant_ignore=IgnoreReason.TENANT), + field_id('Mutation', 'startReindexCatalog'): TestData(tenant_ignore=IgnoreReason.TENANT), field_id('Mutation', 'startSagemakerNotebook'): TestData(tenant_perm=MANAGE_NOTEBOOKS), - field_id('Mutation', 'stopMaintenanceWindow'): TestData(tenant_ignore=IgnoreReason.ADMIN), + field_id('Mutation', 'stopMaintenanceWindow'): TestData(tenant_ignore=IgnoreReason.TENANT), field_id('Mutation', 'stopSagemakerNotebook'): TestData(tenant_perm=MANAGE_NOTEBOOKS), field_id('Mutation', 'submitShareExtension'): TestData(tenant_perm=MANAGE_SHARES), field_id('Mutation', 'submitShareObject'): TestData(tenant_perm=MANAGE_SHARES), @@ -242,13 +242,13 @@ def __post_init__(self): field_id('Mutation', 'updateEnvironment'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), field_id('Mutation', 'updateGlossary'): TestData(tenant_perm=MANAGE_GLOSSARIES), field_id('Mutation', 'updateGroupEnvironmentPermissions'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), - field_id('Mutation', 'updateGroupTenantPermissions'): TestData(tenant_ignore=IgnoreReason.ADMIN), + field_id('Mutation', 'updateGroupTenantPermissions'): TestData(tenant_ignore=IgnoreReason.TENANT), field_id('Mutation', 'updateKeyValueTags'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), field_id('Mutation', 'updateOrganization'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), field_id('Mutation', 'updateOrganizationGroup'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), field_id('Mutation', 'updateRedshiftDataset'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), field_id('Mutation', 'updateRedshiftDatasetTable'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), - field_id('Mutation', 'updateSSMParameter'): TestData(tenant_ignore=IgnoreReason.ADMIN), + field_id('Mutation', 'updateSSMParameter'): TestData(tenant_ignore=IgnoreReason.TENANT), field_id('Mutation', 'updateShareExpirationPeriod'): TestData(tenant_perm=MANAGE_SHARES), field_id('Mutation', 'updateShareExtensionReason'): TestData(tenant_perm=MANAGE_SHARES), field_id('Mutation', 'updateShareItemFilters'): TestData(tenant_perm=MANAGE_SHARES), From b557d8144ce285789a7ef270f2e5d0688883799f Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Mon, 2 Dec 2024 11:06:16 +0200 Subject: [PATCH 26/47] appsupport --- tests/test_tenant_unauthorized.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index a0775e1e4..6afe41f8b 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -36,9 +36,7 @@ def resolver_id(type_name, field_name): class IgnoreReason(Enum): TENANT = 'admin action. No need for tenant permission check' - SUPPORT = 'permissions do not apply to support notifications' - FEED = 'permissions do not apply to support feed messages' - VOTES = 'permissions do not apply to support votes' + APPSUPPORT = 'permissions do not apply to application support features (Feed/Votes)' BACKPORT = 'outside of this PR to be able to backport to v2.6.2' INTRAMODULE = 'returns intra-module data' PERMCHECK = 'checks user permissions for a particular feature' @@ -82,7 +80,7 @@ def __post_init__(self): field_id('ConsumptionRole', 'managedPolicies'): TestData(resource_perm=GET_ENVIRONMENT), field_id('Dashboard', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), field_id('Dashboard', 'terms'): TestData(resource_ignore=IgnoreReason.CATALOG), - field_id('Dashboard', 'upvotes'): TestData(resource_ignore=IgnoreReason.VOTES), + field_id('Dashboard', 'upvotes'): TestData(resource_ignore=IgnoreReason.APPSUPPORT), field_id('Dashboard', 'userRoleForDashboard'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('DataPipeline', 'cloneUrlHttp'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('DataPipeline', 'developmentEnvironments'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), @@ -121,7 +119,7 @@ def __post_init__(self): field_id('Environment', 'userRoleInEnvironment'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('EnvironmentSimplified', 'networks'): TestData(resource_perm=GET_NETWORK), field_id('EnvironmentSimplified', 'organization'): TestData(resource_ignore=IgnoreReason.SIMPLIFIED), - field_id('Feed', 'messages'): TestData(resource_ignore=IgnoreReason.FEED), + field_id('Feed', 'messages'): TestData(resource_ignore=IgnoreReason.APPSUPPORT), field_id('Glossary', 'associations'): TestData(resource_ignore=IgnoreReason.CATALOG), field_id('Glossary', 'categories'): TestData(resource_ignore=IgnoreReason.CATALOG), field_id('Glossary', 'children'): TestData(resource_ignore=IgnoreReason.CATALOG), @@ -186,7 +184,7 @@ def __post_init__(self): field_id('Mutation', 'deleteMetadataFormField'): TestData(tenant_perm=MANAGE_METADATA_FORMS), field_id('Mutation', 'deleteMetadataFormVersion'): TestData(tenant_perm=MANAGE_METADATA_FORMS), field_id('Mutation', 'deleteNetwork'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), - field_id('Mutation', 'deleteNotification'): TestData(tenant_ignore=IgnoreReason.SUPPORT), + field_id('Mutation', 'deleteNotification'): TestData(tenant_ignore=IgnoreReason.APPSUPPORT), field_id('Mutation', 'deleteOmicsRun'): TestData(tenant_perm=MANAGE_OMICS_RUNS), field_id('Mutation', 'deleteRedshiftConnection'): TestData(tenant_ignore=IgnoreReason.BACKPORT), field_id('Mutation', 'deleteRedshiftDataset'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), @@ -205,8 +203,8 @@ def __post_init__(self): field_id('Mutation', 'importRedshiftDataset'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), field_id('Mutation', 'inviteGroupOnEnvironment'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), field_id('Mutation', 'inviteGroupToOrganization'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), - field_id('Mutation', 'markNotificationAsRead'): TestData(tenant_ignore=IgnoreReason.SUPPORT), - field_id('Mutation', 'postFeedMessage'): TestData(tenant_ignore=IgnoreReason.FEED), + field_id('Mutation', 'markNotificationAsRead'): TestData(tenant_ignore=IgnoreReason.APPSUPPORT), + field_id('Mutation', 'postFeedMessage'): TestData(tenant_ignore=IgnoreReason.APPSUPPORT), field_id('Mutation', 'reApplyItemsShareObject'): TestData(tenant_perm=MANAGE_SHARES), field_id('Mutation', 'reApplyShareObjectItemsOnDataset'): TestData(tenant_perm=MANAGE_DATASETS), field_id('Mutation', 'rejectDashboardShare'): TestData(tenant_perm=MANAGE_DASHBOARDS), @@ -229,7 +227,7 @@ def __post_init__(self): field_id('Mutation', 'submitShareObject'): TestData(tenant_perm=MANAGE_SHARES), field_id('Mutation', 'syncDatasetTableColumns'): TestData(tenant_perm=MANAGE_DATASETS), field_id('Mutation', 'syncTables'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'upVote'): TestData(tenant_ignore=IgnoreReason.VOTES), + field_id('Mutation', 'upVote'): TestData(tenant_ignore=IgnoreReason.APPSUPPORT), field_id('Mutation', 'updateCategory'): TestData(tenant_perm=MANAGE_GLOSSARIES), field_id('Mutation', 'updateConsumptionRole'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), field_id('Mutation', 'updateDashboard'): TestData(tenant_perm=MANAGE_DASHBOARDS), @@ -387,7 +385,7 @@ def __post_init__(self): field_id('RedshiftDataset', 'owners'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('RedshiftDataset', 'stewards'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('RedshiftDataset', 'terms'): TestData(resource_ignore=IgnoreReason.CATALOG), - field_id('RedshiftDataset', 'upvotes'): TestData(resource_ignore=IgnoreReason.VOTES), + field_id('RedshiftDataset', 'upvotes'): TestData(resource_ignore=IgnoreReason.APPSUPPORT), field_id('RedshiftDataset', 'userRoleForDataset'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('RedshiftDatasetTable', 'dataset'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('RedshiftDatasetTable', 'terms'): TestData(resource_ignore=IgnoreReason.CATALOG), From b9cc73be8edc0e9e3b15ca178bc2ad0a10a47cc9 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Mon, 2 Dec 2024 11:08:48 +0200 Subject: [PATCH 27/47] improve IgnoreReason --- tests/test_tenant_unauthorized.py | 60 ++++++++++++++++--------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index 6afe41f8b..4c17ec3c0 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -36,11 +36,11 @@ def resolver_id(type_name, field_name): class IgnoreReason(Enum): TENANT = 'admin action. No need for tenant permission check' - APPSUPPORT = 'permissions do not apply to application support features (Feed/Votes)' + APPSUPPORT = 'permissions do not apply to application support features' BACKPORT = 'outside of this PR to be able to backport to v2.6.2' INTRAMODULE = 'returns intra-module data' - PERMCHECK = 'checks user permissions for a particular feature' - CATALOG = 'catalog resources are public by design' + USERROLEINRESOURCE = 'checks user permissions for a particular feature' + PUBLIC = 'public by design' SIMPLIFIED = 'simplified response' NOTREQUIRED = 'permission check is not required' @@ -61,9 +61,9 @@ class TestData: def __post_init__(self): if not any([self.resource_perm, self.resource_ignore]): - raise ValueError("Either resource_perm or resource_ignore must be set") + raise ValueError('Either resource_perm or resource_ignore must be set') if not any([self.tenant_perm, self.tenant_ignore]): - raise ValueError("Either tenant_perm or tenant_ignore must be set") + raise ValueError('Either tenant_perm or tenant_ignore must be set') EXPECTED_RESOLVERS: Mapping[str, TestData] = { @@ -71,7 +71,9 @@ def __post_init__(self): field_id('AttachedMetadataForm', 'fields'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('AttachedMetadataForm', 'metadataForm'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('AttachedMetadataFormField', 'field'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('AttachedMetadataFormField', 'hasTenantPermissions'): TestData(resource_ignore=IgnoreReason.PERMCHECK), + field_id('AttachedMetadataFormField', 'hasTenantPermissions'): TestData( + resource_ignore=IgnoreReason.USERROLEINRESOURCE + ), field_id('Category', 'associations'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('Category', 'categories'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('Category', 'children'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), @@ -79,7 +81,7 @@ def __post_init__(self): field_id('Category', 'terms'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('ConsumptionRole', 'managedPolicies'): TestData(resource_perm=GET_ENVIRONMENT), field_id('Dashboard', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), - field_id('Dashboard', 'terms'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('Dashboard', 'terms'): TestData(resource_ignore=IgnoreReason.PUBLIC), field_id('Dashboard', 'upvotes'): TestData(resource_ignore=IgnoreReason.APPSUPPORT), field_id('Dashboard', 'userRoleForDashboard'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('DataPipeline', 'cloneUrlHttp'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), @@ -95,7 +97,7 @@ def __post_init__(self): field_id('Dataset', 'statistics'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('Dataset', 'stewards'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('Dataset', 'tables'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Dataset', 'terms'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('Dataset', 'terms'): TestData(resource_ignore=IgnoreReason.PUBLIC), field_id('Dataset', 'userRoleForDataset'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('DatasetBase', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), field_id('DatasetBase', 'owners'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), @@ -106,12 +108,12 @@ def __post_init__(self): field_id('DatasetProfilingRun', 'results'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('DatasetProfilingRun', 'status'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('DatasetStorageLocation', 'dataset'): TestData(resource_perm=GET_DATASET), - field_id('DatasetStorageLocation', 'terms'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('DatasetStorageLocation', 'terms'): TestData(resource_ignore=IgnoreReason.PUBLIC), field_id('DatasetTable', 'GlueTableProperties'): TestData(resource_perm=GET_DATASET_TABLE), field_id('DatasetTable', 'columns'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('DatasetTable', 'dataset'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('DatasetTable', 'terms'): TestData(resource_ignore=IgnoreReason.CATALOG), - field_id('DatasetTableColumn', 'terms'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('DatasetTable', 'terms'): TestData(resource_ignore=IgnoreReason.PUBLIC), + field_id('DatasetTableColumn', 'terms'): TestData(resource_ignore=IgnoreReason.PUBLIC), field_id('Environment', 'networks'): TestData(resource_perm=GET_NETWORK), field_id('Environment', 'organization'): TestData(resource_ignore=IgnoreReason.SIMPLIFIED), field_id('Environment', 'parameters'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), @@ -120,21 +122,23 @@ def __post_init__(self): field_id('EnvironmentSimplified', 'networks'): TestData(resource_perm=GET_NETWORK), field_id('EnvironmentSimplified', 'organization'): TestData(resource_ignore=IgnoreReason.SIMPLIFIED), field_id('Feed', 'messages'): TestData(resource_ignore=IgnoreReason.APPSUPPORT), - field_id('Glossary', 'associations'): TestData(resource_ignore=IgnoreReason.CATALOG), - field_id('Glossary', 'categories'): TestData(resource_ignore=IgnoreReason.CATALOG), - field_id('Glossary', 'children'): TestData(resource_ignore=IgnoreReason.CATALOG), - field_id('Glossary', 'stats'): TestData(resource_ignore=IgnoreReason.CATALOG), - field_id('Glossary', 'tree'): TestData(resource_ignore=IgnoreReason.CATALOG), - field_id('Glossary', 'userRoleForGlossary'): TestData(resource_ignore=IgnoreReason.CATALOG), - field_id('GlossaryTermLink', 'target'): TestData(resource_ignore=IgnoreReason.CATALOG), - field_id('GlossaryTermLink', 'term'): TestData(resource_ignore=IgnoreReason.CATALOG), - field_id('Group', 'environmentPermissions'): TestData(resource_ignore=IgnoreReason.PERMCHECK), - field_id('Group', 'tenantPermissions'): TestData(resource_ignore=IgnoreReason.PERMCHECK), + field_id('Glossary', 'associations'): TestData(resource_ignore=IgnoreReason.PUBLIC), + field_id('Glossary', 'categories'): TestData(resource_ignore=IgnoreReason.PUBLIC), + field_id('Glossary', 'children'): TestData(resource_ignore=IgnoreReason.PUBLIC), + field_id('Glossary', 'stats'): TestData(resource_ignore=IgnoreReason.PUBLIC), + field_id('Glossary', 'tree'): TestData(resource_ignore=IgnoreReason.PUBLIC), + field_id('Glossary', 'userRoleForGlossary'): TestData(resource_ignore=IgnoreReason.PUBLIC), + field_id('GlossaryTermLink', 'target'): TestData(resource_ignore=IgnoreReason.PUBLIC), + field_id('GlossaryTermLink', 'term'): TestData(resource_ignore=IgnoreReason.PUBLIC), + field_id('Group', 'environmentPermissions'): TestData(resource_ignore=IgnoreReason.USERROLEINRESOURCE), + field_id('Group', 'tenantPermissions'): TestData(resource_ignore=IgnoreReason.USERROLEINRESOURCE), field_id('MetadataForm', 'fields'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('MetadataForm', 'homeEntityName'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('MetadataForm', 'userRole'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('MetadataFormField', 'glossaryNodeName'): TestData(resource_ignore=IgnoreReason.CATALOG), - field_id('MetadataFormSearchResult', 'hasTenantPermissions'): TestData(resource_ignore=IgnoreReason.PERMCHECK), + field_id('MetadataFormField', 'glossaryNodeName'): TestData(resource_ignore=IgnoreReason.PUBLIC), + field_id('MetadataFormSearchResult', 'hasTenantPermissions'): TestData( + resource_ignore=IgnoreReason.USERROLEINRESOURCE + ), field_id('Mutation', 'DisableDataSubscriptions'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), field_id('Mutation', 'addConnectionGroupPermission'): TestData(tenant_ignore=IgnoreReason.BACKPORT), field_id('Mutation', 'addConsumptionRoleToEnvironment'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), @@ -384,11 +388,11 @@ def __post_init__(self): field_id('RedshiftDataset', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), field_id('RedshiftDataset', 'owners'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('RedshiftDataset', 'stewards'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('RedshiftDataset', 'terms'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('RedshiftDataset', 'terms'): TestData(resource_ignore=IgnoreReason.PUBLIC), field_id('RedshiftDataset', 'upvotes'): TestData(resource_ignore=IgnoreReason.APPSUPPORT), field_id('RedshiftDataset', 'userRoleForDataset'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('RedshiftDatasetTable', 'dataset'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('RedshiftDatasetTable', 'terms'): TestData(resource_ignore=IgnoreReason.CATALOG), + field_id('RedshiftDatasetTable', 'terms'): TestData(resource_ignore=IgnoreReason.PUBLIC), field_id('SagemakerNotebook', 'NotebookInstanceStatus'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('SagemakerNotebook', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), field_id('SagemakerNotebook', 'organization'): TestData(resource_perm=GET_ORGANIZATION), @@ -411,7 +415,7 @@ def __post_init__(self): field_id('ShareObject', 'items'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('ShareObject', 'principal'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('ShareObject', 'statistics'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('ShareObject', 'userRoleForShareObject'): TestData(resource_ignore=IgnoreReason.PERMCHECK), + field_id('ShareObject', 'userRoleForShareObject'): TestData(resource_ignore=IgnoreReason.USERROLEINRESOURCE), field_id('SharedDatabaseTableItem', 'sharedGlueDatabaseName'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('Stack', 'EcsTaskId'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), field_id('Stack', 'canViewLogs'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), @@ -429,9 +433,9 @@ def __post_init__(self): def test_all_resolvers_have_test_data(): - ''' + """ ensure that all EXPECTED_RESOURCES_PERMS have a corresponding query (to avoid stale entries) and vice versa - ''' + """ assert_that([field_id(res[0].name, res[1].name) for res in ALL_RESOLVERS]).described_as( 'stale or missing EXPECTED_RESOURCE_PERMS detected' ).contains_only(*EXPECTED_RESOLVERS.keys()) From f60b2ba22bd0964cc52778f991b1f068bfcb17db Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Mon, 2 Dec 2024 11:13:20 +0200 Subject: [PATCH 28/47] dispatch all --- frontend/src/modules/Folders/views/FolderView.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/src/modules/Folders/views/FolderView.js b/frontend/src/modules/Folders/views/FolderView.js index 23f882c69..7b70a7e70 100644 --- a/frontend/src/modules/Folders/views/FolderView.js +++ b/frontend/src/modules/Folders/views/FolderView.js @@ -242,8 +242,9 @@ const FolderView = () => { ); } else { setFolder(null); - const error = response.errors[0].message; - dispatch({ type: SET_ERROR, error }); + response.errors.forEach((err) => + dispatch({ type: SET_ERROR, error: err.message }) + ); } setLoading(false); }, [client, dispatch, params.uri]); From 921b83042da1b4e4529525b749c2e3de99021a43 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Mon, 2 Dec 2024 12:16:14 +0200 Subject: [PATCH 29/47] explicit tests --- tests/test_tenant_unauthorized.py | 1430 +++++++++++++++++++++-------- 1 file changed, 1058 insertions(+), 372 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index 4c17ec3c0..7c2db9dc5 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -18,7 +18,7 @@ from dataall.core.permissions.services.tenant_permissions import MANAGE_ENVIRONMENTS, MANAGE_ORGANIZATIONS from dataall.core.permissions.services.tenant_policy_service import TenantPolicyService from dataall.modules.catalog.services.glossaries_permissions import MANAGE_GLOSSARIES -from dataall.modules.dashboards.services.dashboard_permissions import MANAGE_DASHBOARDS +from dataall.modules.dashboards.services.dashboard_permissions import MANAGE_DASHBOARDS, SHARE_DASHBOARD from dataall.modules.datapipelines.services.datapipelines_permissions import GET_PIPELINE, MANAGE_PIPELINES from dataall.modules.metadata_forms.services.metadata_form_permissions import MANAGE_METADATA_FORMS from dataall.modules.mlstudio.services.mlstudio_permissions import GET_SGMSTUDIO_USER, MANAGE_SGMSTUDIO_USERS @@ -30,10 +30,6 @@ from dataall.modules.worksheets.services.worksheet_permissions import MANAGE_WORKSHEETS -def resolver_id(type_name, field_name): - return f'{type_name}_{field_name}' - - class IgnoreReason(Enum): TENANT = 'admin action. No need for tenant permission check' APPSUPPORT = 'permissions do not apply to application support features' @@ -42,6 +38,9 @@ class IgnoreReason(Enum): USERROLEINRESOURCE = 'checks user permissions for a particular feature' PUBLIC = 'public by design' SIMPLIFIED = 'simplified response' + USERLIMITED = 'returns user resources in application' + CUSTOM = 'custom permissions checks' + ADMINLIMITED = 'limited to resource owners/admin' NOTREQUIRED = 'permission check is not required' @@ -49,388 +48,1075 @@ def field_id(type_name: str, field_name: str) -> str: return f'{type_name}_{field_name}' -ALL_RESOLVERS = {(_type, field) for _type in bootstrap().types for field in _type.fields if field.resolver} - - @dataclass class TestData: - resource_ignore: IgnoreReason = IgnoreReason.NOTREQUIRED + resource_ignore: IgnoreReason = None resource_perm: str = None - tenant_ignore: IgnoreReason = IgnoreReason.NOTREQUIRED + tenant_ignore: IgnoreReason = None tenant_perm: str = None def __post_init__(self): - if not any([self.resource_perm, self.resource_ignore]): + if not bool(self.resource_perm) ^ bool(self.resource_ignore): raise ValueError('Either resource_perm or resource_ignore must be set') - if not any([self.tenant_perm, self.tenant_ignore]): + if not bool(self.tenant_perm) ^ bool(self.tenant_ignore): raise ValueError('Either tenant_perm or tenant_ignore must be set') EXPECTED_RESOLVERS: Mapping[str, TestData] = { - field_id('AttachedMetadataForm', 'entityName'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('AttachedMetadataForm', 'fields'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('AttachedMetadataForm', 'metadataForm'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('AttachedMetadataFormField', 'field'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + field_id('AttachedMetadataForm', 'entityName'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('AttachedMetadataForm', 'fields'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('AttachedMetadataForm', 'metadataForm'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('AttachedMetadataFormField', 'field'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), field_id('AttachedMetadataFormField', 'hasTenantPermissions'): TestData( - resource_ignore=IgnoreReason.USERROLEINRESOURCE - ), - field_id('Category', 'associations'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Category', 'categories'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Category', 'children'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Category', 'stats'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Category', 'terms'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('ConsumptionRole', 'managedPolicies'): TestData(resource_perm=GET_ENVIRONMENT), - field_id('Dashboard', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), - field_id('Dashboard', 'terms'): TestData(resource_ignore=IgnoreReason.PUBLIC), - field_id('Dashboard', 'upvotes'): TestData(resource_ignore=IgnoreReason.APPSUPPORT), - field_id('Dashboard', 'userRoleForDashboard'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('DataPipeline', 'cloneUrlHttp'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('DataPipeline', 'developmentEnvironments'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('DataPipeline', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), - field_id('DataPipeline', 'organization'): TestData(resource_perm=GET_ORGANIZATION), - field_id('DataPipeline', 'stack'): TestData(resource_perm=GET_PIPELINE), - field_id('DataPipeline', 'userRoleForPipeline'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Dataset', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), - field_id('Dataset', 'locations'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Dataset', 'owners'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Dataset', 'stack'): TestData(resource_perm=GET_DATASET), - field_id('Dataset', 'statistics'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Dataset', 'stewards'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Dataset', 'tables'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Dataset', 'terms'): TestData(resource_ignore=IgnoreReason.PUBLIC), - field_id('Dataset', 'userRoleForDataset'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('DatasetBase', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), - field_id('DatasetBase', 'owners'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('DatasetBase', 'stack'): TestData(resource_perm=GET_DATASET), - field_id('DatasetBase', 'stewards'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('DatasetBase', 'userRoleForDataset'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('DatasetProfilingRun', 'dataset'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('DatasetProfilingRun', 'results'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('DatasetProfilingRun', 'status'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('DatasetStorageLocation', 'dataset'): TestData(resource_perm=GET_DATASET), - field_id('DatasetStorageLocation', 'terms'): TestData(resource_ignore=IgnoreReason.PUBLIC), - field_id('DatasetTable', 'GlueTableProperties'): TestData(resource_perm=GET_DATASET_TABLE), - field_id('DatasetTable', 'columns'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('DatasetTable', 'dataset'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('DatasetTable', 'terms'): TestData(resource_ignore=IgnoreReason.PUBLIC), - field_id('DatasetTableColumn', 'terms'): TestData(resource_ignore=IgnoreReason.PUBLIC), - field_id('Environment', 'networks'): TestData(resource_perm=GET_NETWORK), - field_id('Environment', 'organization'): TestData(resource_ignore=IgnoreReason.SIMPLIFIED), - field_id('Environment', 'parameters'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Environment', 'stack'): TestData(resource_perm=GET_ENVIRONMENT), - field_id('Environment', 'userRoleInEnvironment'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('EnvironmentSimplified', 'networks'): TestData(resource_perm=GET_NETWORK), - field_id('EnvironmentSimplified', 'organization'): TestData(resource_ignore=IgnoreReason.SIMPLIFIED), - field_id('Feed', 'messages'): TestData(resource_ignore=IgnoreReason.APPSUPPORT), - field_id('Glossary', 'associations'): TestData(resource_ignore=IgnoreReason.PUBLIC), - field_id('Glossary', 'categories'): TestData(resource_ignore=IgnoreReason.PUBLIC), - field_id('Glossary', 'children'): TestData(resource_ignore=IgnoreReason.PUBLIC), - field_id('Glossary', 'stats'): TestData(resource_ignore=IgnoreReason.PUBLIC), - field_id('Glossary', 'tree'): TestData(resource_ignore=IgnoreReason.PUBLIC), - field_id('Glossary', 'userRoleForGlossary'): TestData(resource_ignore=IgnoreReason.PUBLIC), - field_id('GlossaryTermLink', 'target'): TestData(resource_ignore=IgnoreReason.PUBLIC), - field_id('GlossaryTermLink', 'term'): TestData(resource_ignore=IgnoreReason.PUBLIC), - field_id('Group', 'environmentPermissions'): TestData(resource_ignore=IgnoreReason.USERROLEINRESOURCE), - field_id('Group', 'tenantPermissions'): TestData(resource_ignore=IgnoreReason.USERROLEINRESOURCE), - field_id('MetadataForm', 'fields'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('MetadataForm', 'homeEntityName'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('MetadataForm', 'userRole'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('MetadataFormField', 'glossaryNodeName'): TestData(resource_ignore=IgnoreReason.PUBLIC), + resource_ignore=IgnoreReason.USERROLEINRESOURCE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Category', 'associations'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Category', 'categories'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Category', 'children'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Category', 'stats'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Category', 'terms'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('ConsumptionRole', 'managedPolicies'): TestData( + resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Dashboard', 'environment'): TestData( + resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Dashboard', 'terms'): TestData( + resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Dashboard', 'upvotes'): TestData( + resource_ignore=IgnoreReason.APPSUPPORT, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Dashboard', 'userRoleForDashboard'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('DataPipeline', 'cloneUrlHttp'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('DataPipeline', 'developmentEnvironments'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('DataPipeline', 'environment'): TestData( + resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('DataPipeline', 'organization'): TestData( + resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('DataPipeline', 'stack'): TestData(resource_perm=GET_PIPELINE, tenant_ignore=IgnoreReason.NOTREQUIRED), + field_id('DataPipeline', 'userRoleForPipeline'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Dataset', 'environment'): TestData(resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED), + field_id('Dataset', 'locations'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Dataset', 'owners'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Dataset', 'stack'): TestData(resource_perm=GET_DATASET, tenant_ignore=IgnoreReason.NOTREQUIRED), + field_id('Dataset', 'statistics'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Dataset', 'stewards'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Dataset', 'tables'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Dataset', 'terms'): TestData(resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.NOTREQUIRED), + field_id('Dataset', 'userRoleForDataset'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('DatasetBase', 'environment'): TestData( + resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('DatasetBase', 'owners'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('DatasetBase', 'stack'): TestData(resource_perm=GET_DATASET, tenant_ignore=IgnoreReason.NOTREQUIRED), + field_id('DatasetBase', 'stewards'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('DatasetBase', 'userRoleForDataset'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('DatasetProfilingRun', 'dataset'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('DatasetProfilingRun', 'results'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('DatasetProfilingRun', 'status'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('DatasetStorageLocation', 'dataset'): TestData( + resource_perm=GET_DATASET, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('DatasetStorageLocation', 'terms'): TestData( + resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('DatasetTable', 'GlueTableProperties'): TestData( + resource_perm=GET_DATASET_TABLE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('DatasetTable', 'columns'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('DatasetTable', 'dataset'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('DatasetTable', 'terms'): TestData( + resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('DatasetTableColumn', 'terms'): TestData( + resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Environment', 'networks'): TestData(resource_perm=GET_NETWORK, tenant_ignore=IgnoreReason.NOTREQUIRED), + field_id('Environment', 'organization'): TestData( + resource_ignore=IgnoreReason.SIMPLIFIED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Environment', 'parameters'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Environment', 'stack'): TestData(resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED), + field_id('Environment', 'userRoleInEnvironment'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('EnvironmentSimplified', 'networks'): TestData( + resource_perm=GET_NETWORK, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('EnvironmentSimplified', 'organization'): TestData( + resource_ignore=IgnoreReason.SIMPLIFIED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Feed', 'messages'): TestData( + resource_ignore=IgnoreReason.APPSUPPORT, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Glossary', 'associations'): TestData( + resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Glossary', 'categories'): TestData( + resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Glossary', 'children'): TestData( + resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Glossary', 'stats'): TestData( + resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Glossary', 'tree'): TestData(resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.NOTREQUIRED), + field_id('Glossary', 'userRoleForGlossary'): TestData( + resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('GlossaryTermLink', 'target'): TestData( + resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('GlossaryTermLink', 'term'): TestData( + resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Group', 'environmentPermissions'): TestData( + resource_ignore=IgnoreReason.USERROLEINRESOURCE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Group', 'tenantPermissions'): TestData( + resource_ignore=IgnoreReason.USERROLEINRESOURCE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('MetadataForm', 'fields'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('MetadataForm', 'homeEntityName'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('MetadataForm', 'userRole'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('MetadataFormField', 'glossaryNodeName'): TestData( + resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.NOTREQUIRED + ), field_id('MetadataFormSearchResult', 'hasTenantPermissions'): TestData( - resource_ignore=IgnoreReason.USERROLEINRESOURCE - ), - field_id('Mutation', 'DisableDataSubscriptions'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), - field_id('Mutation', 'addConnectionGroupPermission'): TestData(tenant_ignore=IgnoreReason.BACKPORT), - field_id('Mutation', 'addConsumptionRoleToEnvironment'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), - field_id('Mutation', 'addRedshiftDatasetTables'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), - field_id('Mutation', 'addSharedItem'): TestData(tenant_perm=MANAGE_SHARES), - field_id('Mutation', 'approveDashboardShare'): TestData(tenant_perm=MANAGE_DASHBOARDS), - field_id('Mutation', 'approveShareExtension'): TestData(tenant_perm=MANAGE_SHARES), - field_id('Mutation', 'approveShareObject'): TestData(tenant_perm=MANAGE_SHARES), - field_id('Mutation', 'approveTermAssociation'): TestData(tenant_perm=MANAGE_GLOSSARIES), - field_id('Mutation', 'archiveOrganization'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), - field_id('Mutation', 'batchMetadataFormFieldUpdates'): TestData(tenant_perm=MANAGE_METADATA_FORMS), - field_id('Mutation', 'cancelShareExtension'): TestData(tenant_perm=MANAGE_SHARES), - field_id('Mutation', 'createAttachedMetadataForm'): TestData(tenant_ignore=IgnoreReason.BACKPORT), - field_id('Mutation', 'createCategory'): TestData(tenant_perm=MANAGE_GLOSSARIES), - field_id('Mutation', 'createDataPipeline'): TestData(tenant_perm=MANAGE_PIPELINES), - field_id('Mutation', 'createDataPipelineEnvironment'): TestData(tenant_perm=MANAGE_PIPELINES), - field_id('Mutation', 'createDataset'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'createDatasetStorageLocation'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'createEnvironment'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), - field_id('Mutation', 'createGlossary'): TestData(tenant_perm=MANAGE_GLOSSARIES), - field_id('Mutation', 'createMetadataForm'): TestData(tenant_perm=MANAGE_METADATA_FORMS), - field_id('Mutation', 'createMetadataFormFields'): TestData(tenant_perm=MANAGE_METADATA_FORMS), - field_id('Mutation', 'createMetadataFormVersion'): TestData(tenant_perm=MANAGE_METADATA_FORMS), - field_id('Mutation', 'createNetwork'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), - field_id('Mutation', 'createOmicsRun'): TestData(tenant_perm=MANAGE_OMICS_RUNS), - field_id('Mutation', 'createOrganization'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), - field_id('Mutation', 'createQuicksightDataSourceSet'): TestData(tenant_ignore=IgnoreReason.TENANT), - field_id('Mutation', 'createRedshiftConnection'): TestData(tenant_ignore=IgnoreReason.BACKPORT), - field_id('Mutation', 'createSagemakerNotebook'): TestData(tenant_perm=MANAGE_NOTEBOOKS), - field_id('Mutation', 'createSagemakerStudioUser'): TestData(tenant_perm=MANAGE_SGMSTUDIO_USERS), - field_id('Mutation', 'createShareObject'): TestData(tenant_perm=MANAGE_SHARES), - field_id('Mutation', 'createTableDataFilter'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'createTerm'): TestData(tenant_perm=MANAGE_GLOSSARIES), - field_id('Mutation', 'createWorksheet'): TestData(tenant_perm=MANAGE_WORKSHEETS), - field_id('Mutation', 'deleteAttachedMetadataForm'): TestData(tenant_ignore=IgnoreReason.BACKPORT), - field_id('Mutation', 'deleteCategory'): TestData(tenant_perm=MANAGE_GLOSSARIES), - field_id('Mutation', 'deleteConnectionGroupPermission'): TestData(tenant_ignore=IgnoreReason.BACKPORT), - field_id('Mutation', 'deleteDashboard'): TestData(tenant_perm=MANAGE_DASHBOARDS), - field_id('Mutation', 'deleteDataPipeline'): TestData(tenant_perm=MANAGE_PIPELINES), - field_id('Mutation', 'deleteDataPipelineEnvironment'): TestData(tenant_perm=MANAGE_PIPELINES), - field_id('Mutation', 'deleteDataset'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'deleteDatasetStorageLocation'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'deleteDatasetTable'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'deleteEnvironment'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), - field_id('Mutation', 'deleteGlossary'): TestData(tenant_perm=MANAGE_GLOSSARIES), - field_id('Mutation', 'deleteMetadataForm'): TestData(tenant_perm=MANAGE_METADATA_FORMS), - field_id('Mutation', 'deleteMetadataFormField'): TestData(tenant_perm=MANAGE_METADATA_FORMS), - field_id('Mutation', 'deleteMetadataFormVersion'): TestData(tenant_perm=MANAGE_METADATA_FORMS), - field_id('Mutation', 'deleteNetwork'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), - field_id('Mutation', 'deleteNotification'): TestData(tenant_ignore=IgnoreReason.APPSUPPORT), - field_id('Mutation', 'deleteOmicsRun'): TestData(tenant_perm=MANAGE_OMICS_RUNS), - field_id('Mutation', 'deleteRedshiftConnection'): TestData(tenant_ignore=IgnoreReason.BACKPORT), - field_id('Mutation', 'deleteRedshiftDataset'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), - field_id('Mutation', 'deleteRedshiftDatasetTable'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), - field_id('Mutation', 'deleteSagemakerNotebook'): TestData(tenant_perm=MANAGE_NOTEBOOKS), - field_id('Mutation', 'deleteSagemakerStudioUser'): TestData(tenant_perm=MANAGE_SGMSTUDIO_USERS), - field_id('Mutation', 'deleteShareObject'): TestData(tenant_perm=MANAGE_SHARES), - field_id('Mutation', 'deleteTableDataFilter'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'deleteTerm'): TestData(tenant_perm=MANAGE_GLOSSARIES), - field_id('Mutation', 'deleteWorksheet'): TestData(tenant_perm=MANAGE_WORKSHEETS), - field_id('Mutation', 'dismissTermAssociation'): TestData(tenant_perm=MANAGE_GLOSSARIES), - field_id('Mutation', 'enableDataSubscriptions'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), - field_id('Mutation', 'generateDatasetAccessToken'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'importDashboard'): TestData(tenant_perm=MANAGE_DASHBOARDS), - field_id('Mutation', 'importDataset'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'importRedshiftDataset'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), - field_id('Mutation', 'inviteGroupOnEnvironment'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), - field_id('Mutation', 'inviteGroupToOrganization'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), - field_id('Mutation', 'markNotificationAsRead'): TestData(tenant_ignore=IgnoreReason.APPSUPPORT), - field_id('Mutation', 'postFeedMessage'): TestData(tenant_ignore=IgnoreReason.APPSUPPORT), - field_id('Mutation', 'reApplyItemsShareObject'): TestData(tenant_perm=MANAGE_SHARES), - field_id('Mutation', 'reApplyShareObjectItemsOnDataset'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'rejectDashboardShare'): TestData(tenant_perm=MANAGE_DASHBOARDS), - field_id('Mutation', 'rejectShareObject'): TestData(tenant_perm=MANAGE_SHARES), - field_id('Mutation', 'removeConsumptionRoleFromEnvironment'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), - field_id('Mutation', 'removeGroupFromEnvironment'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), - field_id('Mutation', 'removeGroupFromOrganization'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), - field_id('Mutation', 'removeShareItemFilter'): TestData(tenant_perm=MANAGE_SHARES), - field_id('Mutation', 'removeSharedItem'): TestData(tenant_perm=MANAGE_SHARES), - field_id('Mutation', 'requestDashboardShare'): TestData(tenant_perm=MANAGE_DASHBOARDS), - field_id('Mutation', 'revokeItemsShareObject'): TestData(tenant_perm=MANAGE_SHARES), - field_id('Mutation', 'startDatasetProfilingRun'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'startGlueCrawler'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'startMaintenanceWindow'): TestData(tenant_ignore=IgnoreReason.TENANT), - field_id('Mutation', 'startReindexCatalog'): TestData(tenant_ignore=IgnoreReason.TENANT), - field_id('Mutation', 'startSagemakerNotebook'): TestData(tenant_perm=MANAGE_NOTEBOOKS), - field_id('Mutation', 'stopMaintenanceWindow'): TestData(tenant_ignore=IgnoreReason.TENANT), - field_id('Mutation', 'stopSagemakerNotebook'): TestData(tenant_perm=MANAGE_NOTEBOOKS), - field_id('Mutation', 'submitShareExtension'): TestData(tenant_perm=MANAGE_SHARES), - field_id('Mutation', 'submitShareObject'): TestData(tenant_perm=MANAGE_SHARES), - field_id('Mutation', 'syncDatasetTableColumns'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'syncTables'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'upVote'): TestData(tenant_ignore=IgnoreReason.APPSUPPORT), - field_id('Mutation', 'updateCategory'): TestData(tenant_perm=MANAGE_GLOSSARIES), - field_id('Mutation', 'updateConsumptionRole'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), - field_id('Mutation', 'updateDashboard'): TestData(tenant_perm=MANAGE_DASHBOARDS), - field_id('Mutation', 'updateDataPipeline'): TestData(tenant_perm=MANAGE_PIPELINES), - field_id('Mutation', 'updateDataPipelineEnvironment'): TestData(tenant_perm=MANAGE_PIPELINES), - field_id('Mutation', 'updateDataset'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'updateDatasetStorageLocation'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'updateDatasetTable'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'updateDatasetTableColumn'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'updateEnvironment'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), - field_id('Mutation', 'updateGlossary'): TestData(tenant_perm=MANAGE_GLOSSARIES), - field_id('Mutation', 'updateGroupEnvironmentPermissions'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), - field_id('Mutation', 'updateGroupTenantPermissions'): TestData(tenant_ignore=IgnoreReason.TENANT), - field_id('Mutation', 'updateKeyValueTags'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), - field_id('Mutation', 'updateOrganization'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), - field_id('Mutation', 'updateOrganizationGroup'): TestData(tenant_perm=MANAGE_ORGANIZATIONS), - field_id('Mutation', 'updateRedshiftDataset'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), - field_id('Mutation', 'updateRedshiftDatasetTable'): TestData(tenant_perm=MANAGE_REDSHIFT_DATASETS), - field_id('Mutation', 'updateSSMParameter'): TestData(tenant_ignore=IgnoreReason.TENANT), - field_id('Mutation', 'updateShareExpirationPeriod'): TestData(tenant_perm=MANAGE_SHARES), - field_id('Mutation', 'updateShareExtensionReason'): TestData(tenant_perm=MANAGE_SHARES), - field_id('Mutation', 'updateShareItemFilters'): TestData(tenant_perm=MANAGE_SHARES), - field_id('Mutation', 'updateShareRejectReason'): TestData(tenant_perm=MANAGE_SHARES), - field_id('Mutation', 'updateShareRequestReason'): TestData(tenant_perm=MANAGE_SHARES), - field_id('Mutation', 'updateStack'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), - field_id('Mutation', 'updateTerm'): TestData(tenant_perm=MANAGE_GLOSSARIES), - field_id('Mutation', 'updateWorksheet'): TestData(tenant_perm=MANAGE_WORKSHEETS), - field_id('Mutation', 'verifyDatasetShareObjects'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Mutation', 'verifyItemsShareObject'): TestData(tenant_perm=MANAGE_SHARES), - field_id('OmicsRun', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), - field_id('OmicsRun', 'organization'): TestData(resource_perm=GET_ORGANIZATION), - field_id('OmicsRun', 'status'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('OmicsRun', 'workflow'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Organization', 'environments'): TestData(resource_perm=GET_ORGANIZATION), - field_id('Organization', 'stats'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Organization', 'userRoleInOrganization'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Permission', 'type'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Query', 'countDeletedNotifications'): TestData(), - field_id('Query', 'countReadNotifications'): TestData(), - field_id('Query', 'countUnreadNotifications'): TestData(), - field_id('Query', 'countUpVotes'): TestData(), - field_id('Query', 'generateEnvironmentAccessToken'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), - field_id('Query', 'getAttachedMetadataForm'): TestData(), - field_id('Query', 'getAuthorSession'): TestData(), - field_id('Query', 'getCDKExecPolicyPresignedUrl'): TestData(), - field_id('Query', 'getConsumptionRolePolicies'): TestData(), - field_id('Query', 'getDashboard'): TestData(), - field_id('Query', 'getDataPipeline'): TestData(), - field_id('Query', 'getDataPipelineCredsLinux'): TestData(), - field_id('Query', 'getDataset'): TestData(), - field_id('Query', 'getDatasetAssumeRoleUrl'): TestData(tenant_perm=MANAGE_DATASETS), - field_id('Query', 'getDatasetPresignedUrl'): TestData(), - field_id('Query', 'getDatasetSharedAssumeRoleUrl'): TestData(), - field_id('Query', 'getDatasetStorageLocation'): TestData(), - field_id('Query', 'getDatasetTable'): TestData(), - field_id('Query', 'getDatasetTableProfilingRun'): TestData(), - field_id('Query', 'getEntityMetadataFormPermissions'): TestData(), - field_id('Query', 'getEnvironment'): TestData(), - field_id('Query', 'getEnvironmentAssumeRoleUrl'): TestData(tenant_perm=MANAGE_ENVIRONMENTS), - field_id('Query', 'getEnvironmentMLStudioDomain'): TestData(), - field_id('Query', 'getFeed'): TestData(), - field_id('Query', 'getGlossary'): TestData(), - field_id('Query', 'getGroup'): TestData(), - field_id('Query', 'getGroupsForUser'): TestData(), - field_id('Query', 'getMaintenanceWindowStatus'): TestData(), - field_id('Query', 'getMetadataForm'): TestData(), - field_id('Query', 'getMonitoringDashboardId'): TestData(), - field_id('Query', 'getMonitoringVPCConnectionId'): TestData(), - field_id('Query', 'getOmicsWorkflow'): TestData(), - field_id('Query', 'getOrganization'): TestData(), - field_id('Query', 'getPivotRoleExternalId'): TestData(), - field_id('Query', 'getPivotRoleName'): TestData(), - field_id('Query', 'getPivotRolePresignedUrl'): TestData(), - field_id('Query', 'getPlatformAuthorSession'): TestData(), - field_id('Query', 'getPlatformReaderSession'): TestData(), - field_id('Query', 'getReaderSession'): TestData(), - field_id('Query', 'getRedshiftDataset'): TestData(), - field_id('Query', 'getRedshiftDatasetTable'): TestData(), - field_id('Query', 'getRedshiftDatasetTableColumns'): TestData(), - field_id('Query', 'getS3ConsumptionData'): TestData(), - field_id('Query', 'getSagemakerNotebook'): TestData(), - field_id('Query', 'getSagemakerNotebookPresignedUrl'): TestData(tenant_perm=MANAGE_NOTEBOOKS), - field_id('Query', 'getSagemakerStudioUser'): TestData(), - field_id('Query', 'getSagemakerStudioUserPresignedUrl'): TestData(tenant_perm=MANAGE_SGMSTUDIO_USERS), - field_id('Query', 'getShareItemDataFilters'): TestData(), - field_id('Query', 'getShareLogs'): TestData(), - field_id('Query', 'getShareObject'): TestData(), - field_id('Query', 'getShareRequestsFromMe'): TestData(), - field_id('Query', 'getShareRequestsToMe'): TestData(), - field_id('Query', 'getSharedDatasetTables'): TestData(), - field_id('Query', 'getStack'): TestData(), - field_id('Query', 'getStackLogs'): TestData(), - field_id('Query', 'getTrustAccount'): TestData(), - field_id('Query', 'getVote'): TestData(), - field_id('Query', 'getWorksheet'): TestData(), - field_id('Query', 'listAllConsumptionRoles'): TestData(), - field_id('Query', 'listAllEnvironmentConsumptionRoles'): TestData(), - field_id('Query', 'listAllEnvironmentGroups'): TestData(), - field_id('Query', 'listAllGroups'): TestData(), - field_id('Query', 'listAttachedMetadataForms'): TestData(), - field_id('Query', 'listConnectionGroupNoPermissions'): TestData(), - field_id('Query', 'listConnectionGroupPermissions'): TestData(), - field_id('Query', 'listDashboardShares'): TestData(), - field_id('Query', 'listDataPipelines'): TestData(), - field_id('Query', 'listDatasetTableColumns'): TestData(), - field_id('Query', 'listDatasetTableProfilingRuns'): TestData(), - field_id('Query', 'listDatasetTables'): TestData(), - field_id('Query', 'listDatasets'): TestData(), - field_id('Query', 'listDatasetsCreatedInEnvironment'): TestData(), - field_id('Query', 'listEntityMetadataForms'): TestData(), - field_id('Query', 'listEnvironmentConsumptionRoles'): TestData(), - field_id('Query', 'listEnvironmentGroupInvitationPermissions'): TestData(), - field_id('Query', 'listEnvironmentGroups'): TestData(), - field_id('Query', 'listEnvironmentInvitedGroups'): TestData(), - field_id('Query', 'listEnvironmentNetworks'): TestData(), - field_id('Query', 'listEnvironmentRedshiftConnections'): TestData(), - field_id('Query', 'listEnvironments'): TestData(), - field_id('Query', 'listGlossaries'): TestData(), - field_id('Query', 'listGroups'): TestData(), - field_id('Query', 'listInviteOrganizationPermissionsWithDescriptions'): TestData(), - field_id('Query', 'listKeyValueTags'): TestData(), - field_id('Query', 'listMetadataFormVersions'): TestData(), - field_id('Query', 'listNotifications'): TestData(), - field_id('Query', 'listOmicsRuns'): TestData(), - field_id('Query', 'listOmicsWorkflows'): TestData(), - field_id('Query', 'listOrganizationGroupPermissions'): TestData(), - field_id('Query', 'listOrganizationGroups'): TestData(), - field_id('Query', 'listOrganizations'): TestData(), - field_id('Query', 'listOwnedDatasets'): TestData(), - field_id('Query', 'listRedshiftConnectionSchemas'): TestData(), - field_id('Query', 'listRedshiftDatasetTables'): TestData(), - field_id('Query', 'listRedshiftSchemaDatasetTables'): TestData(), - field_id('Query', 'listRedshiftSchemaTables'): TestData(), - field_id('Query', 'listS3DatasetsOwnedByEnvGroup'): TestData(), - field_id('Query', 'listS3DatasetsSharedWithEnvGroup'): TestData(), - field_id('Query', 'listSagemakerNotebooks'): TestData(), - field_id('Query', 'listSagemakerStudioUsers'): TestData(), - field_id('Query', 'listSharedDatasetTableColumns'): TestData(), - field_id('Query', 'listTableDataFilters'): TestData(), - field_id('Query', 'listTableDataFiltersByAttached'): TestData(), - field_id('Query', 'listTenantGroups'): TestData(), - field_id('Query', 'listTenantPermissions'): TestData(), - field_id('Query', 'listUserMetadataForms'): TestData(), - field_id('Query', 'listUsersForGroup'): TestData(), - field_id('Query', 'listValidEnvironments'): TestData(), - field_id('Query', 'listWorksheets'): TestData(), - field_id('Query', 'previewTable'): TestData(), - field_id('Query', 'queryEnums'): TestData(), - field_id('Query', 'runAthenaSqlQuery'): TestData(), - field_id('Query', 'searchDashboards'): TestData(), - field_id('Query', 'searchEnvironmentDataItems'): TestData(), - field_id('Query', 'searchGlossary'): TestData(), - field_id('RedshiftDataset', 'connection'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('RedshiftDataset', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), - field_id('RedshiftDataset', 'owners'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('RedshiftDataset', 'stewards'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('RedshiftDataset', 'terms'): TestData(resource_ignore=IgnoreReason.PUBLIC), - field_id('RedshiftDataset', 'upvotes'): TestData(resource_ignore=IgnoreReason.APPSUPPORT), - field_id('RedshiftDataset', 'userRoleForDataset'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('RedshiftDatasetTable', 'dataset'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('RedshiftDatasetTable', 'terms'): TestData(resource_ignore=IgnoreReason.PUBLIC), - field_id('SagemakerNotebook', 'NotebookInstanceStatus'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('SagemakerNotebook', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), - field_id('SagemakerNotebook', 'organization'): TestData(resource_perm=GET_ORGANIZATION), - field_id('SagemakerNotebook', 'stack'): TestData(resource_perm=GET_NOTEBOOK), - field_id('SagemakerNotebook', 'userRoleForNotebook'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('SagemakerStudioDomain', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), - field_id('SagemakerStudioUser', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), - field_id('SagemakerStudioUser', 'organization'): TestData(resource_perm=GET_ORGANIZATION), - field_id('SagemakerStudioUser', 'sagemakerStudioUserApps'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('SagemakerStudioUser', 'sagemakerStudioUserStatus'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('SagemakerStudioUser', 'stack'): TestData(resource_perm=GET_SGMSTUDIO_USER), + resource_ignore=IgnoreReason.USERROLEINRESOURCE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'DisableDataSubscriptions'): TestData( + tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'addConnectionGroupPermission'): TestData( + tenant_ignore=IgnoreReason.BACKPORT, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'addConsumptionRoleToEnvironment'): TestData( + tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'addRedshiftDatasetTables'): TestData( + tenant_perm=MANAGE_REDSHIFT_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'addSharedItem'): TestData( + tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'approveDashboardShare'): TestData( + tenant_perm=MANAGE_DASHBOARDS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'approveShareExtension'): TestData( + tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'approveShareObject'): TestData( + tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'approveTermAssociation'): TestData( + tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'archiveOrganization'): TestData( + tenant_perm=MANAGE_ORGANIZATIONS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'batchMetadataFormFieldUpdates'): TestData( + tenant_perm=MANAGE_METADATA_FORMS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'cancelShareExtension'): TestData( + tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createAttachedMetadataForm'): TestData( + tenant_ignore=IgnoreReason.BACKPORT, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createCategory'): TestData( + tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createDataPipeline'): TestData( + tenant_perm=MANAGE_PIPELINES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createDataPipelineEnvironment'): TestData( + tenant_perm=MANAGE_PIPELINES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createDataset'): TestData( + tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createDatasetStorageLocation'): TestData( + tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createEnvironment'): TestData( + tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createGlossary'): TestData( + tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createMetadataForm'): TestData( + tenant_perm=MANAGE_METADATA_FORMS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createMetadataFormFields'): TestData( + tenant_perm=MANAGE_METADATA_FORMS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createMetadataFormVersion'): TestData( + tenant_perm=MANAGE_METADATA_FORMS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createNetwork'): TestData( + tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createOmicsRun'): TestData( + tenant_perm=MANAGE_OMICS_RUNS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createOrganization'): TestData( + tenant_perm=MANAGE_ORGANIZATIONS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createQuicksightDataSourceSet'): TestData( + tenant_ignore=IgnoreReason.TENANT, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createRedshiftConnection'): TestData( + tenant_ignore=IgnoreReason.BACKPORT, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createSagemakerNotebook'): TestData( + tenant_perm=MANAGE_NOTEBOOKS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createSagemakerStudioUser'): TestData( + tenant_perm=MANAGE_SGMSTUDIO_USERS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createShareObject'): TestData( + tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createTableDataFilter'): TestData( + tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createTerm'): TestData( + tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'createWorksheet'): TestData( + tenant_perm=MANAGE_WORKSHEETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteAttachedMetadataForm'): TestData( + tenant_ignore=IgnoreReason.BACKPORT, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteCategory'): TestData( + tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteConnectionGroupPermission'): TestData( + tenant_ignore=IgnoreReason.BACKPORT, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteDashboard'): TestData( + tenant_perm=MANAGE_DASHBOARDS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteDataPipeline'): TestData( + tenant_perm=MANAGE_PIPELINES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteDataPipelineEnvironment'): TestData( + tenant_perm=MANAGE_PIPELINES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteDataset'): TestData( + tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteDatasetStorageLocation'): TestData( + tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteDatasetTable'): TestData( + tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteEnvironment'): TestData( + tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteGlossary'): TestData( + tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteMetadataForm'): TestData( + tenant_perm=MANAGE_METADATA_FORMS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteMetadataFormField'): TestData( + tenant_perm=MANAGE_METADATA_FORMS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteMetadataFormVersion'): TestData( + tenant_perm=MANAGE_METADATA_FORMS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteNetwork'): TestData( + tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteNotification'): TestData( + tenant_ignore=IgnoreReason.APPSUPPORT, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteOmicsRun'): TestData( + tenant_perm=MANAGE_OMICS_RUNS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteRedshiftConnection'): TestData( + tenant_ignore=IgnoreReason.BACKPORT, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteRedshiftDataset'): TestData( + tenant_perm=MANAGE_REDSHIFT_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteRedshiftDatasetTable'): TestData( + tenant_perm=MANAGE_REDSHIFT_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteSagemakerNotebook'): TestData( + tenant_perm=MANAGE_NOTEBOOKS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteSagemakerStudioUser'): TestData( + tenant_perm=MANAGE_SGMSTUDIO_USERS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteShareObject'): TestData( + tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteTableDataFilter'): TestData( + tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteTerm'): TestData( + tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'deleteWorksheet'): TestData( + tenant_perm=MANAGE_WORKSHEETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'dismissTermAssociation'): TestData( + tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'enableDataSubscriptions'): TestData( + tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'generateDatasetAccessToken'): TestData( + tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'importDashboard'): TestData( + tenant_perm=MANAGE_DASHBOARDS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'importDataset'): TestData( + tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'importRedshiftDataset'): TestData( + tenant_perm=MANAGE_REDSHIFT_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'inviteGroupOnEnvironment'): TestData( + tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'inviteGroupToOrganization'): TestData( + tenant_perm=MANAGE_ORGANIZATIONS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'markNotificationAsRead'): TestData( + tenant_ignore=IgnoreReason.APPSUPPORT, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'postFeedMessage'): TestData( + tenant_ignore=IgnoreReason.APPSUPPORT, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'reApplyItemsShareObject'): TestData( + tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'reApplyShareObjectItemsOnDataset'): TestData( + tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'rejectDashboardShare'): TestData( + tenant_perm=MANAGE_DASHBOARDS, resource_perm=SHARE_DASHBOARD + ), + field_id('Mutation', 'rejectShareObject'): TestData( + tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'removeConsumptionRoleFromEnvironment'): TestData( + tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'removeGroupFromEnvironment'): TestData( + tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'removeGroupFromOrganization'): TestData( + tenant_perm=MANAGE_ORGANIZATIONS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'removeShareItemFilter'): TestData( + tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'removeSharedItem'): TestData( + tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'requestDashboardShare'): TestData( + tenant_perm=MANAGE_DASHBOARDS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'revokeItemsShareObject'): TestData( + tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'startDatasetProfilingRun'): TestData( + tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'startGlueCrawler'): TestData( + tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'startMaintenanceWindow'): TestData( + tenant_ignore=IgnoreReason.TENANT, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'startReindexCatalog'): TestData( + tenant_ignore=IgnoreReason.TENANT, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'startSagemakerNotebook'): TestData( + tenant_perm=MANAGE_NOTEBOOKS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'stopMaintenanceWindow'): TestData( + tenant_ignore=IgnoreReason.TENANT, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'stopSagemakerNotebook'): TestData( + tenant_perm=MANAGE_NOTEBOOKS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'submitShareExtension'): TestData( + tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'submitShareObject'): TestData( + tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'syncDatasetTableColumns'): TestData( + tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'syncTables'): TestData(tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED), + field_id('Mutation', 'upVote'): TestData( + tenant_ignore=IgnoreReason.APPSUPPORT, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateCategory'): TestData( + tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateConsumptionRole'): TestData( + tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateDashboard'): TestData( + tenant_perm=MANAGE_DASHBOARDS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateDataPipeline'): TestData( + tenant_perm=MANAGE_PIPELINES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateDataPipelineEnvironment'): TestData( + tenant_perm=MANAGE_PIPELINES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateDataset'): TestData( + tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateDatasetStorageLocation'): TestData( + tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateDatasetTable'): TestData( + tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateDatasetTableColumn'): TestData( + tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateEnvironment'): TestData( + tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateGlossary'): TestData( + tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateGroupEnvironmentPermissions'): TestData( + tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateGroupTenantPermissions'): TestData( + tenant_ignore=IgnoreReason.TENANT, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateKeyValueTags'): TestData( + tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateOrganization'): TestData( + tenant_perm=MANAGE_ORGANIZATIONS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateOrganizationGroup'): TestData( + tenant_perm=MANAGE_ORGANIZATIONS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateRedshiftDataset'): TestData( + tenant_perm=MANAGE_REDSHIFT_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateRedshiftDatasetTable'): TestData( + tenant_perm=MANAGE_REDSHIFT_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateSSMParameter'): TestData( + tenant_ignore=IgnoreReason.TENANT, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateShareExpirationPeriod'): TestData( + tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateShareExtensionReason'): TestData( + tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateShareItemFilters'): TestData( + tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateShareRejectReason'): TestData( + tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateShareRequestReason'): TestData( + tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateStack'): TestData( + tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateTerm'): TestData( + tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'updateWorksheet'): TestData( + tenant_perm=MANAGE_WORKSHEETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'verifyDatasetShareObjects'): TestData( + tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Mutation', 'verifyItemsShareObject'): TestData( + tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('OmicsRun', 'environment'): TestData( + resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('OmicsRun', 'organization'): TestData( + resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('OmicsRun', 'status'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('OmicsRun', 'workflow'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Organization', 'environments'): TestData( + resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Organization', 'stats'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Organization', 'userRoleInOrganization'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Permission', 'type'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'countDeletedNotifications'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'countReadNotifications'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'countUnreadNotifications'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'countUpVotes'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'generateEnvironmentAccessToken'): TestData( + tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getAttachedMetadataForm'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getAuthorSession'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getCDKExecPolicyPresignedUrl'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getConsumptionRolePolicies'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getDashboard'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getDataPipeline'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getDataPipelineCredsLinux'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getDataset'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getDatasetAssumeRoleUrl'): TestData( + tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getDatasetPresignedUrl'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getDatasetSharedAssumeRoleUrl'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getDatasetStorageLocation'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getDatasetTable'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getDatasetTableProfilingRun'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getEntityMetadataFormPermissions'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getEnvironment'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getEnvironmentAssumeRoleUrl'): TestData( + tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getEnvironmentMLStudioDomain'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getFeed'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getGlossary'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getGroup'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getGroupsForUser'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getMaintenanceWindowStatus'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getMetadataForm'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getMonitoringDashboardId'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getMonitoringVPCConnectionId'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getOmicsWorkflow'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getOrganization'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getPivotRoleExternalId'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getPivotRoleName'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getPivotRolePresignedUrl'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getPlatformAuthorSession'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getPlatformReaderSession'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getReaderSession'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getRedshiftDataset'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getRedshiftDatasetTable'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getRedshiftDatasetTableColumns'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getS3ConsumptionData'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getSagemakerNotebook'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getSagemakerNotebookPresignedUrl'): TestData( + tenant_perm=MANAGE_NOTEBOOKS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getSagemakerStudioUser'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getSagemakerStudioUserPresignedUrl'): TestData( + tenant_perm=MANAGE_SGMSTUDIO_USERS, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getShareItemDataFilters'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getShareLogs'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getShareObject'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getShareRequestsFromMe'): TestData( + tenant_ignore=IgnoreReason.USERLIMITED, resource_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getShareRequestsToMe'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getSharedDatasetTables'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getStack'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getStackLogs'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getTrustAccount'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getVote'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'getWorksheet'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listAllConsumptionRoles'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listAllEnvironmentConsumptionRoles'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listAllEnvironmentGroups'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listAllGroups'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listAttachedMetadataForms'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listConnectionGroupNoPermissions'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listConnectionGroupPermissions'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listDashboardShares'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listDataPipelines'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listDatasetTableColumns'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listDatasetTableProfilingRuns'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listDatasetTables'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listDatasets'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listDatasetsCreatedInEnvironment'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listEntityMetadataForms'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listEnvironmentConsumptionRoles'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listEnvironmentGroupInvitationPermissions'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listEnvironmentGroups'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listEnvironmentInvitedGroups'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listEnvironmentNetworks'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listEnvironmentRedshiftConnections'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listEnvironments'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listGlossaries'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listGroups'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listInviteOrganizationPermissionsWithDescriptions'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listKeyValueTags'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listMetadataFormVersions'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listNotifications'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listOmicsRuns'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listOmicsWorkflows'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listOrganizationGroupPermissions'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listOrganizationGroups'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listOrganizations'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listOwnedDatasets'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listRedshiftConnectionSchemas'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listRedshiftDatasetTables'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listRedshiftSchemaDatasetTables'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listRedshiftSchemaTables'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listS3DatasetsOwnedByEnvGroup'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listS3DatasetsSharedWithEnvGroup'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listSagemakerNotebooks'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listSagemakerStudioUsers'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listSharedDatasetTableColumns'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listTableDataFilters'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listTableDataFiltersByAttached'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listTenantGroups'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listTenantPermissions'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listUserMetadataForms'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listUsersForGroup'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listValidEnvironments'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'listWorksheets'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'previewTable'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'queryEnums'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'runAthenaSqlQuery'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'searchDashboards'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'searchEnvironmentDataItems'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Query', 'searchGlossary'): TestData( + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('RedshiftDataset', 'connection'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('RedshiftDataset', 'environment'): TestData( + resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('RedshiftDataset', 'owners'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('RedshiftDataset', 'stewards'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('RedshiftDataset', 'terms'): TestData( + resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('RedshiftDataset', 'upvotes'): TestData( + resource_ignore=IgnoreReason.APPSUPPORT, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('RedshiftDataset', 'userRoleForDataset'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('RedshiftDatasetTable', 'dataset'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('RedshiftDatasetTable', 'terms'): TestData( + resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('SagemakerNotebook', 'NotebookInstanceStatus'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('SagemakerNotebook', 'environment'): TestData( + resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('SagemakerNotebook', 'organization'): TestData( + resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('SagemakerNotebook', 'stack'): TestData( + resource_perm=GET_NOTEBOOK, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('SagemakerNotebook', 'userRoleForNotebook'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('SagemakerStudioDomain', 'environment'): TestData( + resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('SagemakerStudioUser', 'environment'): TestData( + resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('SagemakerStudioUser', 'organization'): TestData( + resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('SagemakerStudioUser', 'sagemakerStudioUserApps'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('SagemakerStudioUser', 'sagemakerStudioUserStatus'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('SagemakerStudioUser', 'stack'): TestData( + resource_perm=GET_SGMSTUDIO_USER, tenant_ignore=IgnoreReason.NOTREQUIRED + ), field_id('SagemakerStudioUser', 'userRoleForSagemakerStudioUser'): TestData( - resource_ignore=IgnoreReason.INTRAMODULE - ), - field_id('ShareObject', 'canViewLogs'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('ShareObject', 'dataset'): TestData(resource_ignore=IgnoreReason.SIMPLIFIED), - field_id('ShareObject', 'environment'): TestData(resource_perm=GET_ENVIRONMENT), - field_id('ShareObject', 'existingSharedItems'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('ShareObject', 'group'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('ShareObject', 'items'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('ShareObject', 'principal'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('ShareObject', 'statistics'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('ShareObject', 'userRoleForShareObject'): TestData(resource_ignore=IgnoreReason.USERROLEINRESOURCE), - field_id('SharedDatabaseTableItem', 'sharedGlueDatabaseName'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Stack', 'EcsTaskId'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Stack', 'canViewLogs'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Stack', 'error'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Stack', 'events'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Stack', 'link'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Stack', 'outputs'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Stack', 'resources'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Term', 'associations'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Term', 'children'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Term', 'glossary'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Term', 'stats'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), - field_id('Worksheet', 'userRoleForWorksheet'): TestData(resource_ignore=IgnoreReason.INTRAMODULE), + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('ShareObject', 'canViewLogs'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('ShareObject', 'dataset'): TestData( + resource_ignore=IgnoreReason.SIMPLIFIED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('ShareObject', 'environment'): TestData( + resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('ShareObject', 'existingSharedItems'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('ShareObject', 'group'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('ShareObject', 'items'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('ShareObject', 'principal'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('ShareObject', 'statistics'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('ShareObject', 'userRoleForShareObject'): TestData( + resource_ignore=IgnoreReason.USERROLEINRESOURCE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('SharedDatabaseTableItem', 'sharedGlueDatabaseName'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Stack', 'EcsTaskId'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Stack', 'canViewLogs'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Stack', 'error'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Stack', 'events'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Stack', 'link'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Stack', 'outputs'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Stack', 'resources'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Term', 'associations'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Term', 'children'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Term', 'glossary'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Term', 'stats'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), + field_id('Worksheet', 'userRoleForWorksheet'): TestData( + resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + ), } +ALL_RESOLVERS = {(_type, field) for _type in bootstrap().types for field in _type.fields if field.resolver} + def test_all_resolvers_have_test_data(): """ @@ -517,7 +1203,7 @@ def test_unauthorized_resource_permissions( msg = f'{fid} -> {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' expected_perm = tdata.resource_perm if not expected_perm: - pytest.skip(msg + f' Reason: {tdata.tenant_ignore.value}') + pytest.skip(msg + f' Reason: {tdata.resource_ignore.value}') logging.info(msg) assert_that(field.resolver).is_not_none() From 616319708663fd82c6c0c5bf42dbf43d47e57a9b Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Mon, 2 Dec 2024 13:14:47 +0200 Subject: [PATCH 30/47] mock tenant --- tests/test_tenant_unauthorized.py | 36 ++++++++++++++----------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index 7c2db9dc5..948ecfbdc 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -16,7 +16,6 @@ from dataall.core.permissions.services.network_permissions import GET_NETWORK from dataall.core.permissions.services.organization_permissions import GET_ORGANIZATION from dataall.core.permissions.services.tenant_permissions import MANAGE_ENVIRONMENTS, MANAGE_ORGANIZATIONS -from dataall.core.permissions.services.tenant_policy_service import TenantPolicyService from dataall.modules.catalog.services.glossaries_permissions import MANAGE_GLOSSARIES from dataall.modules.dashboards.services.dashboard_permissions import MANAGE_DASHBOARDS, SHARE_DASHBOARD from dataall.modules.datapipelines.services.datapipelines_permissions import GET_PIPELINE, MANAGE_PIPELINES @@ -772,7 +771,7 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getSagemakerNotebookPresignedUrl'): TestData( - tenant_perm=MANAGE_NOTEBOOKS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_NOTEBOOKS, resource_perm=GET_NOTEBOOK ), field_id('Query', 'getSagemakerStudioUser'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -1149,21 +1148,19 @@ def mock_input_validation(mocker): @pytest.mark.parametrize('_type,field', ALL_PARAMS) -@patch( - 'dataall.core.permissions.services.tenant_policy_service.TenantPolicyService.check_user_tenant_permission', - wraps=TenantPolicyService.check_user_tenant_permission, -) @patch('dataall.base.context._request_storage') +@patch('dataall.core.permissions.services.resource_policy_service.ResourcePolicyService.check_user_resource_permission') +@patch('dataall.core.permissions.services.group_policy_service.GroupPolicyService.check_group_environment_permission') +@patch('dataall.core.permissions.services.tenant_policy_service.TenantPolicyService.check_user_tenant_permission') def test_unauthorized_tenant_permissions( - mock_local, - spy_check, + mock_tenant_check, + mock_check_group, + mock_check_resource, + mock_storage, _type, field, request, mock_input_validation, - db, - userNoTenantPermissions, - groupNoTenantPermissions, ): fid = request.node.callspec.id tdata = EXPECTED_RESOLVERS[fid] @@ -1174,14 +1171,13 @@ def test_unauthorized_tenant_permissions( logging.info(msg) assert_that(field.resolver).is_not_none() - groups = [groupNoTenantPermissions.groupUri] - username = userNoTenantPermissions.username - mock_local.context = RequestContext(db, username, groups, userNoTenantPermissions) - # Mocking arguments + username = 'ausername' + groups = ['agroup'] + mock_storage.context = RequestContext(MagicMock(), username, groups, 'auserid') + mock_tenant_check.side_effect = TenantUnauthorized(username, 'test_action', 'test_tenant') iargs = {arg: MagicMock() for arg in inspect.signature(field.resolver).parameters.keys()} - # Assert Unauthorized exception is raised assert_that(field.resolver).raises(TenantUnauthorized).when_called_with(**iargs).contains('UnauthorizedOperation') - spy_check.assert_called_once_with( + mock_tenant_check.assert_called_once_with( session=ANY, username=username, groups=groups, tenant_name=ANY, permission_name=expected_perm ) @@ -1191,7 +1187,7 @@ def test_unauthorized_tenant_permissions( @patch('dataall.base.context._request_storage') @pytest.mark.parametrize('_type,field', ALL_PARAMS) def test_unauthorized_resource_permissions( - mock_local, + mock_storage, mock_check, mock_session, _type, @@ -1209,8 +1205,8 @@ def test_unauthorized_resource_permissions( assert_that(field.resolver).is_not_none() username = 'ausername' groups = ['agroup'] - mock_local.context = RequestContext(MagicMock(), username, groups, 'auserid') - mock_local.context.db_engine.scoped_session().__enter__().query().filter().all.return_value = [MagicMock()] + mock_storage.context = RequestContext(MagicMock(), username, groups, 'auserid') + mock_storage.context.db_engine.scoped_session().__enter__().query().filter().all.return_value = [MagicMock()] mock_check.side_effect = ResourceUnauthorized(groups, 'test_action', 'test_uri') iargs = {arg: MagicMock() for arg in inspect.signature(field.resolver).parameters.keys()} with suppress(ResourceUnauthorized): From c3b221d45d5567bdecce2baa7b579331096ae8ff Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Mon, 2 Dec 2024 13:41:31 +0200 Subject: [PATCH 31/47] indirect check support using TargetType --- tests/test_tenant_unauthorized.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index 948ecfbdc..896a29414 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -1183,12 +1183,14 @@ def test_unauthorized_tenant_permissions( @patch('dataall.base.aws.sts.SessionHelper.remote_session') +@patch('dataall.core.stacks.db.target_type_repositories.TargetType.get_resource_read_permission_name') @patch('dataall.core.permissions.services.resource_policy_service.ResourcePolicyService.check_user_resource_permission') @patch('dataall.base.context._request_storage') @pytest.mark.parametrize('_type,field', ALL_PARAMS) def test_unauthorized_resource_permissions( mock_storage, mock_check, + mock_perm_name, mock_session, _type, field, @@ -1208,6 +1210,7 @@ def test_unauthorized_resource_permissions( mock_storage.context = RequestContext(MagicMock(), username, groups, 'auserid') mock_storage.context.db_engine.scoped_session().__enter__().query().filter().all.return_value = [MagicMock()] mock_check.side_effect = ResourceUnauthorized(groups, 'test_action', 'test_uri') + mock_perm_name.return_value = expected_perm iargs = {arg: MagicMock() for arg in inspect.signature(field.resolver).parameters.keys()} with suppress(ResourceUnauthorized): field.resolver(**iargs) From c7395b724941950179ad033ac3cee498241bb7e8 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Mon, 2 Dec 2024 13:48:22 +0200 Subject: [PATCH 32/47] indirect check support using TargetType --- tests/test_tenant_unauthorized.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index 896a29414..f3d9ad823 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -1209,12 +1209,11 @@ def test_unauthorized_resource_permissions( groups = ['agroup'] mock_storage.context = RequestContext(MagicMock(), username, groups, 'auserid') mock_storage.context.db_engine.scoped_session().__enter__().query().filter().all.return_value = [MagicMock()] - mock_check.side_effect = ResourceUnauthorized(groups, 'test_action', 'test_uri') mock_perm_name.return_value = expected_perm iargs = {arg: MagicMock() for arg in inspect.signature(field.resolver).parameters.keys()} - with suppress(ResourceUnauthorized): + with suppress(Exception): field.resolver(**iargs) - mock_check.assert_called_once_with( + mock_check.assert_called_with( session=ANY, resource_uri=ANY, username=username, From 89e27a9a25a4e9b19fc3e4924b39427eef2ffc04 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Mon, 2 Dec 2024 13:53:51 +0200 Subject: [PATCH 33/47] add checks --- tests/test_tenant_unauthorized.py | 69 ++++++++++++++++--------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index f3d9ad823..4b1287a68 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -11,8 +11,9 @@ from dataall.base.api import bootstrap from dataall.base.context import RequestContext -from dataall.base.db.exceptions import TenantUnauthorized, ResourceUnauthorized -from dataall.core.permissions.services.environment_permissions import GET_ENVIRONMENT +from dataall.base.db.exceptions import TenantUnauthorized +from dataall.core.permissions.services.environment_permissions import GET_ENVIRONMENT, LIST_ENVIRONMENT_CONSUMPTION_ROLES, LIST_ENVIRONMENT_NETWORKS, CREDENTIALS_ENVIRONMENT, \ + LIST_ENVIRONMENT_GROUPS from dataall.core.permissions.services.network_permissions import GET_NETWORK from dataall.core.permissions.services.organization_permissions import GET_ORGANIZATION from dataall.core.permissions.services.tenant_permissions import MANAGE_ENVIRONMENTS, MANAGE_ORGANIZATIONS @@ -20,7 +21,7 @@ from dataall.modules.dashboards.services.dashboard_permissions import MANAGE_DASHBOARDS, SHARE_DASHBOARD from dataall.modules.datapipelines.services.datapipelines_permissions import GET_PIPELINE, MANAGE_PIPELINES from dataall.modules.metadata_forms.services.metadata_form_permissions import MANAGE_METADATA_FORMS -from dataall.modules.mlstudio.services.mlstudio_permissions import GET_SGMSTUDIO_USER, MANAGE_SGMSTUDIO_USERS +from dataall.modules.mlstudio.services.mlstudio_permissions import GET_SGMSTUDIO_USER, MANAGE_SGMSTUDIO_USERS, SGMSTUDIO_USER_URL from dataall.modules.notebooks.services.notebook_permissions import GET_NOTEBOOK, MANAGE_NOTEBOOKS from dataall.modules.omics.services.omics_permissions import MANAGE_OMICS_RUNS from dataall.modules.redshift_datasets.services.redshift_dataset_permissions import MANAGE_REDSHIFT_DATASETS @@ -30,13 +31,13 @@ class IgnoreReason(Enum): - TENANT = 'admin action. No need for tenant permission check' + TENANT = 'tenant action, no need for tenant permission check' APPSUPPORT = 'permissions do not apply to application support features' BACKPORT = 'outside of this PR to be able to backport to v2.6.2' INTRAMODULE = 'returns intra-module data' USERROLEINRESOURCE = 'checks user permissions for a particular feature' PUBLIC = 'public by design' - SIMPLIFIED = 'simplified response' + SIMPLIFIED = 'returns a simplified response' USERLIMITED = 'returns user resources in application' CUSTOM = 'custom permissions checks' ADMINLIMITED = 'limited to resource owners/admin' @@ -651,7 +652,7 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'generateEnvironmentAccessToken'): TestData( - tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_ENVIRONMENTS, resource_perm=CREDENTIALS_ENVIRONMENT ), field_id('Query', 'getAttachedMetadataForm'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -660,10 +661,10 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getCDKExecPolicyPresignedUrl'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getConsumptionRolePolicies'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getDashboard'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -699,13 +700,13 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getEnvironment'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getEnvironmentAssumeRoleUrl'): TestData( - tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_ENVIRONMENTS, resource_perm=CREDENTIALS_ENVIRONMENT ), field_id('Query', 'getEnvironmentMLStudioDomain'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getFeed'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -735,7 +736,7 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getOrganization'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getPivotRoleExternalId'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -774,10 +775,10 @@ def __post_init__(self): tenant_perm=MANAGE_NOTEBOOKS, resource_perm=GET_NOTEBOOK ), field_id('Query', 'getSagemakerStudioUser'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_SGMSTUDIO_USER, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getSagemakerStudioUserPresignedUrl'): TestData( - tenant_perm=MANAGE_SGMSTUDIO_USERS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_SGMSTUDIO_USERS, resource_perm=SGMSTUDIO_USER_URL, ), field_id('Query', 'getShareItemDataFilters'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -798,10 +799,10 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getStack'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm='getStack', tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getStackLogs'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm='getStack', tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getTrustAccount'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -813,16 +814,16 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listAllConsumptionRoles'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'listAllEnvironmentConsumptionRoles'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=LIST_ENVIRONMENT_CONSUMPTION_ROLES, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listAllEnvironmentGroups'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=LIST_ENVIRONMENT_GROUPS, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listAllGroups'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'listAttachedMetadataForms'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -858,25 +859,25 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listEnvironmentConsumptionRoles'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=LIST_ENVIRONMENT_CONSUMPTION_ROLES, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listEnvironmentGroupInvitationPermissions'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.USERROLEINRESOURCE, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listEnvironmentGroups'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=LIST_ENVIRONMENT_GROUPS, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listEnvironmentInvitedGroups'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=LIST_ENVIRONMENT_GROUPS, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listEnvironmentNetworks'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=LIST_ENVIRONMENT_NETWORKS, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listEnvironmentRedshiftConnections'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listEnvironments'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'listGlossaries'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -888,7 +889,7 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listKeyValueTags'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm='listKeyValueTags', tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listMetadataFormVersions'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -903,13 +904,13 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listOrganizationGroupPermissions'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listOrganizationGroups'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listOrganizations'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'listOwnedDatasets'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -936,7 +937,7 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listSagemakerStudioUsers'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.USERLIMITED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'listSharedDatasetTableColumns'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -948,10 +949,10 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listTenantGroups'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.TENANT ), field_id('Query', 'listTenantPermissions'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.TENANT ), field_id('Query', 'listUserMetadataForms'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -960,7 +961,7 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listValidEnvironments'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'listWorksheets'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED From dcb42f1ed052e57ac0dd5bef1bf75c2542debcab Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Mon, 2 Dec 2024 15:22:55 +0200 Subject: [PATCH 34/47] add checks --- tests/test_tenant_unauthorized.py | 106 +++++++++++++++--------------- 1 file changed, 54 insertions(+), 52 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index 4b1287a68..0b9a2dd73 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -18,16 +18,17 @@ from dataall.core.permissions.services.organization_permissions import GET_ORGANIZATION from dataall.core.permissions.services.tenant_permissions import MANAGE_ENVIRONMENTS, MANAGE_ORGANIZATIONS from dataall.modules.catalog.services.glossaries_permissions import MANAGE_GLOSSARIES -from dataall.modules.dashboards.services.dashboard_permissions import MANAGE_DASHBOARDS, SHARE_DASHBOARD -from dataall.modules.datapipelines.services.datapipelines_permissions import GET_PIPELINE, MANAGE_PIPELINES +from dataall.modules.dashboards.services.dashboard_permissions import MANAGE_DASHBOARDS, SHARE_DASHBOARD, GET_DASHBOARD, CREATE_DASHBOARD +from dataall.modules.datapipelines.services.datapipelines_permissions import GET_PIPELINE, MANAGE_PIPELINES, CREDENTIALS_PIPELINE +from dataall.modules.datasets_base.services.dataset_list_permissions import LIST_ENVIRONMENT_DATASETS from dataall.modules.metadata_forms.services.metadata_form_permissions import MANAGE_METADATA_FORMS from dataall.modules.mlstudio.services.mlstudio_permissions import GET_SGMSTUDIO_USER, MANAGE_SGMSTUDIO_USERS, SGMSTUDIO_USER_URL from dataall.modules.notebooks.services.notebook_permissions import GET_NOTEBOOK, MANAGE_NOTEBOOKS from dataall.modules.omics.services.omics_permissions import MANAGE_OMICS_RUNS from dataall.modules.redshift_datasets.services.redshift_dataset_permissions import MANAGE_REDSHIFT_DATASETS -from dataall.modules.s3_datasets.services.dataset_permissions import GET_DATASET, GET_DATASET_TABLE, MANAGE_DATASETS -from dataall.modules.shares_base.services.share_permissions import MANAGE_SHARES -from dataall.modules.worksheets.services.worksheet_permissions import MANAGE_WORKSHEETS +from dataall.modules.s3_datasets.services.dataset_permissions import GET_DATASET, GET_DATASET_TABLE, MANAGE_DATASETS, GET_DATASET_FOLDER, CREDENTIALS_DATASET +from dataall.modules.shares_base.services.share_permissions import MANAGE_SHARES, GET_SHARE_OBJECT, LIST_ENVIRONMENT_SHARED_WITH_OBJECTS +from dataall.modules.worksheets.services.worksheet_permissions import MANAGE_WORKSHEETS, GET_WORKSHEET, RUN_ATHENA_QUERY class IgnoreReason(Enum): @@ -646,10 +647,10 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'countUnreadNotifications'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.USERLIMITED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'countUpVotes'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.PUBLIC ), field_id('Query', 'generateEnvironmentAccessToken'): TestData( tenant_perm=MANAGE_ENVIRONMENTS, resource_perm=CREDENTIALS_ENVIRONMENT @@ -658,7 +659,7 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getAuthorSession'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=CREATE_DASHBOARD, tenant_perm=MANAGE_DASHBOARDS ), field_id('Query', 'getCDKExecPolicyPresignedUrl'): TestData( resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -667,34 +668,34 @@ def __post_init__(self): resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getDashboard'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_DASHBOARD, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getDataPipeline'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_PIPELINE, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getDataPipelineCredsLinux'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=CREDENTIALS_PIPELINE, tenant_perm=MANAGE_PIPELINES ), field_id('Query', 'getDataset'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED - ), + ), # TODO Review field_id('Query', 'getDatasetAssumeRoleUrl'): TestData( - tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_DATASETS, resource_perm=CREDENTIALS_DATASET ), field_id('Query', 'getDatasetPresignedUrl'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_DATASETS, resource_perm=CREDENTIALS_DATASET ), field_id('Query', 'getDatasetSharedAssumeRoleUrl'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_DATASETS, resource_perm=CREDENTIALS_DATASET ), field_id('Query', 'getDatasetStorageLocation'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_DATASET_FOLDER, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getDatasetTable'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED - ), + ), # TODO Review field_id('Query', 'getDatasetTableProfilingRun'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.CUSTOM, tenant_ignore=IgnoreReason.CUSTOM ), field_id('Query', 'getEntityMetadataFormPermissions'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -706,13 +707,13 @@ def __post_init__(self): tenant_perm=MANAGE_ENVIRONMENTS, resource_perm=CREDENTIALS_ENVIRONMENT ), field_id('Query', 'getEnvironmentMLStudioDomain'): TestData( - resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED - ), + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + ), # TODO add resource_perm GET_ENVIRONMENT field_id('Query', 'getFeed'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getGlossary'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.PUBLIC ), field_id('Query', 'getGroup'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -721,7 +722,7 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getMaintenanceWindowStatus'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.PUBLIC ), field_id('Query', 'getMetadataForm'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -733,7 +734,7 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getOmicsWorkflow'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.PUBLIC ), field_id('Query', 'getOrganization'): TestData( resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -754,7 +755,7 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getReaderSession'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_DASHBOARD, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getRedshiftDataset'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -766,10 +767,10 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getS3ConsumptionData'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_SHARE_OBJECT, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getSagemakerNotebook'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_NOTEBOOK, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getSagemakerNotebookPresignedUrl'): TestData( tenant_perm=MANAGE_NOTEBOOKS, resource_perm=GET_NOTEBOOK @@ -784,20 +785,20 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getShareLogs'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.CUSTOM, tenant_ignore=IgnoreReason.CUSTOM ), field_id('Query', 'getShareObject'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_SHARE_OBJECT, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getShareRequestsFromMe'): TestData( - tenant_ignore=IgnoreReason.USERLIMITED, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_ignore=IgnoreReason.USERLIMITED, resource_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'getShareRequestsToMe'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.USERLIMITED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'getSharedDatasetTables'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED - ), + ), # TODO Review field_id('Query', 'getStack'): TestData( resource_perm='getStack', tenant_ignore=IgnoreReason.NOTREQUIRED ), @@ -808,10 +809,10 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getVote'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.PUBLIC ), field_id('Query', 'getWorksheet'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_WORKSHEET, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listAllConsumptionRoles'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.USERLIMITED @@ -835,25 +836,25 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listDashboardShares'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.USERLIMITED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'listDataPipelines'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.USERLIMITED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'listDatasetTableColumns'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.CUSTOM, tenant_ignore=IgnoreReason.CUSTOM ), field_id('Query', 'listDatasetTableProfilingRuns'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.CUSTOM, tenant_ignore=IgnoreReason.CUSTOM ), field_id('Query', 'listDatasetTables'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listDatasets'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.USERLIMITED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'listDatasetsCreatedInEnvironment'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=LIST_ENVIRONMENT_DATASETS, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listEntityMetadataForms'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -895,13 +896,13 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listNotifications'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.USERLIMITED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'listOmicsRuns'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.USERLIMITED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'listOmicsWorkflows'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.PUBLIC ), field_id('Query', 'listOrganizationGroupPermissions'): TestData( resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -913,7 +914,7 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'listOwnedDatasets'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.USERLIMITED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'listRedshiftConnectionSchemas'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -928,13 +929,13 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listS3DatasetsOwnedByEnvGroup'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.USERLIMITED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'listS3DatasetsSharedWithEnvGroup'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED - ), + ), # TODO Review field_id('Query', 'listSagemakerNotebooks'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.USERLIMITED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'listSagemakerStudioUsers'): TestData( resource_ignore=IgnoreReason.USERLIMITED, tenant_ignore=IgnoreReason.USERLIMITED @@ -964,22 +965,22 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'listWorksheets'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.USERLIMITED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'previewTable'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.CUSTOM, tenant_ignore=IgnoreReason.CUSTOM ), field_id('Query', 'queryEnums'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'runAthenaSqlQuery'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=RUN_ATHENA_QUERY, tenant_perm=MANAGE_WORKSHEETS ), field_id('Query', 'searchDashboards'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.USERLIMITED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'searchEnvironmentDataItems'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=LIST_ENVIRONMENT_SHARED_WITH_OBJECTS, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'searchGlossary'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -1214,7 +1215,8 @@ def test_unauthorized_resource_permissions( iargs = {arg: MagicMock() for arg in inspect.signature(field.resolver).parameters.keys()} with suppress(Exception): field.resolver(**iargs) - mock_check.assert_called_with( + # TODO add support for asserting multiple calls in case a resolver checks multiple perms + mock_check.assert_any_call( session=ANY, resource_uri=ANY, username=username, From eb770bcd3664dddfd047b98f338fd6b4bf235ca4 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Mon, 2 Dec 2024 16:06:15 +0200 Subject: [PATCH 35/47] add checks --- tests/test_tenant_unauthorized.py | 420 ++++++++++++++++-------------- 1 file changed, 220 insertions(+), 200 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index 0b9a2dd73..bdc450d38 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -12,23 +12,113 @@ from dataall.base.api import bootstrap from dataall.base.context import RequestContext from dataall.base.db.exceptions import TenantUnauthorized -from dataall.core.permissions.services.environment_permissions import GET_ENVIRONMENT, LIST_ENVIRONMENT_CONSUMPTION_ROLES, LIST_ENVIRONMENT_NETWORKS, CREDENTIALS_ENVIRONMENT, \ - LIST_ENVIRONMENT_GROUPS -from dataall.core.permissions.services.network_permissions import GET_NETWORK -from dataall.core.permissions.services.organization_permissions import GET_ORGANIZATION +from dataall.core.permissions.services.environment_permissions import ( + GET_ENVIRONMENT, + LIST_ENVIRONMENT_CONSUMPTION_ROLES, + LIST_ENVIRONMENT_NETWORKS, + CREDENTIALS_ENVIRONMENT, + LIST_ENVIRONMENT_GROUPS, + LIST_ENVIRONMENT_GROUP_PERMISSIONS, + ADD_ENVIRONMENT_CONSUMPTION_ROLES, + CREATE_NETWORK, + ENABLE_ENVIRONMENT_SUBSCRIPTIONS, + DELETE_ENVIRONMENT, + INVITE_ENVIRONMENT_GROUP, + REMOVE_ENVIRONMENT_CONSUMPTION_ROLE, + REMOVE_ENVIRONMENT_GROUP, + UPDATE_ENVIRONMENT, + UPDATE_ENVIRONMENT_GROUP, +) +from dataall.core.permissions.services.network_permissions import GET_NETWORK, DELETE_NETWORK +from dataall.core.permissions.services.organization_permissions import ( + GET_ORGANIZATION, + UPDATE_ORGANIZATION, + DELETE_ORGANIZATION, + INVITE_ORGANIZATION_GROUP, + LINK_ENVIRONMENT, + REMOVE_ORGANIZATION_GROUP, +) from dataall.core.permissions.services.tenant_permissions import MANAGE_ENVIRONMENTS, MANAGE_ORGANIZATIONS from dataall.modules.catalog.services.glossaries_permissions import MANAGE_GLOSSARIES -from dataall.modules.dashboards.services.dashboard_permissions import MANAGE_DASHBOARDS, SHARE_DASHBOARD, GET_DASHBOARD, CREATE_DASHBOARD -from dataall.modules.datapipelines.services.datapipelines_permissions import GET_PIPELINE, MANAGE_PIPELINES, CREDENTIALS_PIPELINE +from dataall.modules.dashboards.services.dashboard_permissions import ( + MANAGE_DASHBOARDS, + SHARE_DASHBOARD, + GET_DASHBOARD, + CREATE_DASHBOARD, + DELETE_DASHBOARD, + UPDATE_DASHBOARD, +) +from dataall.modules.datapipelines.services.datapipelines_permissions import ( + GET_PIPELINE, + MANAGE_PIPELINES, + CREDENTIALS_PIPELINE, + CREATE_PIPELINE, + DELETE_PIPELINE, + UPDATE_PIPELINE, +) from dataall.modules.datasets_base.services.dataset_list_permissions import LIST_ENVIRONMENT_DATASETS -from dataall.modules.metadata_forms.services.metadata_form_permissions import MANAGE_METADATA_FORMS -from dataall.modules.mlstudio.services.mlstudio_permissions import GET_SGMSTUDIO_USER, MANAGE_SGMSTUDIO_USERS, SGMSTUDIO_USER_URL -from dataall.modules.notebooks.services.notebook_permissions import GET_NOTEBOOK, MANAGE_NOTEBOOKS -from dataall.modules.omics.services.omics_permissions import MANAGE_OMICS_RUNS -from dataall.modules.redshift_datasets.services.redshift_dataset_permissions import MANAGE_REDSHIFT_DATASETS -from dataall.modules.s3_datasets.services.dataset_permissions import GET_DATASET, GET_DATASET_TABLE, MANAGE_DATASETS, GET_DATASET_FOLDER, CREDENTIALS_DATASET -from dataall.modules.shares_base.services.share_permissions import MANAGE_SHARES, GET_SHARE_OBJECT, LIST_ENVIRONMENT_SHARED_WITH_OBJECTS -from dataall.modules.worksheets.services.worksheet_permissions import MANAGE_WORKSHEETS, GET_WORKSHEET, RUN_ATHENA_QUERY +from dataall.modules.metadata_forms.services.metadata_form_permissions import ( + MANAGE_METADATA_FORMS, + ATTACH_METADATA_FORM, +) +from dataall.modules.mlstudio.services.mlstudio_permissions import ( + GET_SGMSTUDIO_USER, + MANAGE_SGMSTUDIO_USERS, + SGMSTUDIO_USER_URL, + DELETE_SGMSTUDIO_USER, +) +from dataall.modules.notebooks.services.notebook_permissions import GET_NOTEBOOK, MANAGE_NOTEBOOKS, DELETE_NOTEBOOK +from dataall.modules.omics.services.omics_permissions import MANAGE_OMICS_RUNS, CREATE_OMICS_RUN +from dataall.modules.redshift_datasets.services.redshift_connection_permissions import GET_REDSHIFT_CONNECTION +from dataall.modules.redshift_datasets.services.redshift_dataset_permissions import ( + MANAGE_REDSHIFT_DATASETS, + ADD_TABLES_REDSHIFT_DATASET, + DELETE_REDSHIFT_DATASET, + DELETE_REDSHIFT_DATASET_TABLE, + IMPORT_REDSHIFT_DATASET, + UPDATE_REDSHIFT_DATASET_TABLE, + UPDATE_REDSHIFT_DATASET, + GET_REDSHIFT_DATASET, + GET_REDSHIFT_DATASET_TABLE, +) +from dataall.modules.s3_datasets.services.dataset_permissions import ( + GET_DATASET, + GET_DATASET_TABLE, + MANAGE_DATASETS, + GET_DATASET_FOLDER, + CREDENTIALS_DATASET, + CREATE_TABLE_DATA_FILTER, + DELETE_DATASET_TABLE, + DELETE_DATASET, + DELETE_DATASET_FOLDER, + DELETE_TABLE_DATA_FILTER, + CREATE_DATASET, + UPDATE_DATASET, + PROFILE_DATASET_TABLE, + CRAWL_DATASET, + UPDATE_DATASET_TABLE, + SYNC_DATASET, + UPDATE_DATASET_FOLDER, + LIST_TABLE_DATA_FILTERS, +) +from dataall.modules.shares_base.services.share_permissions import ( + MANAGE_SHARES, + GET_SHARE_OBJECT, + LIST_ENVIRONMENT_SHARED_WITH_OBJECTS, + ADD_ITEM, + APPROVE_SHARE_OBJECT, + SUBMIT_SHARE_OBJECT, + DELETE_SHARE_OBJECT, + REJECT_SHARE_OBJECT, + REMOVE_ITEM, +) +from dataall.modules.worksheets.services.worksheet_permissions import ( + MANAGE_WORKSHEETS, + GET_WORKSHEET, + RUN_ATHENA_QUERY, + DELETE_WORKSHEET, + UPDATE_WORKSHEET, +) class IgnoreReason(Enum): @@ -232,7 +322,7 @@ def __post_init__(self): resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Group', 'environmentPermissions'): TestData( - resource_ignore=IgnoreReason.USERROLEINRESOURCE, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=LIST_ENVIRONMENT_GROUP_PERMISSIONS, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Group', 'tenantPermissions'): TestData( resource_ignore=IgnoreReason.USERROLEINRESOURCE, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -253,52 +343,46 @@ def __post_init__(self): resource_ignore=IgnoreReason.USERROLEINRESOURCE, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Mutation', 'DisableDataSubscriptions'): TestData( - tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_ENVIRONMENTS, resource_perm=ENABLE_ENVIRONMENT_SUBSCRIPTIONS ), field_id('Mutation', 'addConnectionGroupPermission'): TestData( tenant_ignore=IgnoreReason.BACKPORT, resource_ignore=IgnoreReason.NOTREQUIRED ), field_id('Mutation', 'addConsumptionRoleToEnvironment'): TestData( - tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_ENVIRONMENTS, resource_perm=ADD_ENVIRONMENT_CONSUMPTION_ROLES ), field_id('Mutation', 'addRedshiftDatasetTables'): TestData( - tenant_perm=MANAGE_REDSHIFT_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED - ), - field_id('Mutation', 'addSharedItem'): TestData( - tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_REDSHIFT_DATASETS, resource_perm=ADD_TABLES_REDSHIFT_DATASET ), + field_id('Mutation', 'addSharedItem'): TestData(tenant_perm=MANAGE_SHARES, resource_perm=ADD_ITEM), field_id('Mutation', 'approveDashboardShare'): TestData( - tenant_perm=MANAGE_DASHBOARDS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_DASHBOARDS, resource_perm=SHARE_DASHBOARD ), field_id('Mutation', 'approveShareExtension'): TestData( - tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED - ), - field_id('Mutation', 'approveShareObject'): TestData( - tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_SHARES, resource_perm=APPROVE_SHARE_OBJECT ), + field_id('Mutation', 'approveShareObject'): TestData(tenant_perm=MANAGE_SHARES, resource_perm=APPROVE_SHARE_OBJECT), field_id('Mutation', 'approveTermAssociation'): TestData( tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED ), field_id('Mutation', 'archiveOrganization'): TestData( - tenant_perm=MANAGE_ORGANIZATIONS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_ORGANIZATIONS, resource_perm=DELETE_ORGANIZATION ), field_id('Mutation', 'batchMetadataFormFieldUpdates'): TestData( tenant_perm=MANAGE_METADATA_FORMS, resource_ignore=IgnoreReason.NOTREQUIRED ), field_id('Mutation', 'cancelShareExtension'): TestData( - tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_SHARES, resource_perm=SUBMIT_SHARE_OBJECT ), field_id('Mutation', 'createAttachedMetadataForm'): TestData( - tenant_ignore=IgnoreReason.BACKPORT, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_ignore=IgnoreReason.BACKPORT, resource_perm=ATTACH_METADATA_FORM ), field_id('Mutation', 'createCategory'): TestData( tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED ), - field_id('Mutation', 'createDataPipeline'): TestData( - tenant_perm=MANAGE_PIPELINES, resource_ignore=IgnoreReason.NOTREQUIRED - ), + field_id('Mutation', 'createDataPipeline'): TestData(tenant_perm=MANAGE_PIPELINES, resource_perm=CREATE_PIPELINE), field_id('Mutation', 'createDataPipelineEnvironment'): TestData( - tenant_perm=MANAGE_PIPELINES, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_PIPELINES, resource_perm=CREATE_PIPELINE ), field_id('Mutation', 'createDataset'): TestData( tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED @@ -307,7 +391,7 @@ def __post_init__(self): tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED ), field_id('Mutation', 'createEnvironment'): TestData( - tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_ENVIRONMENTS, resource_perm=LINK_ENVIRONMENT ), field_id('Mutation', 'createGlossary'): TestData( tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED @@ -321,12 +405,8 @@ def __post_init__(self): field_id('Mutation', 'createMetadataFormVersion'): TestData( tenant_perm=MANAGE_METADATA_FORMS, resource_ignore=IgnoreReason.NOTREQUIRED ), - field_id('Mutation', 'createNetwork'): TestData( - tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED - ), - field_id('Mutation', 'createOmicsRun'): TestData( - tenant_perm=MANAGE_OMICS_RUNS, resource_ignore=IgnoreReason.NOTREQUIRED - ), + field_id('Mutation', 'createNetwork'): TestData(tenant_perm=MANAGE_ENVIRONMENTS, resource_perm=CREATE_NETWORK), + field_id('Mutation', 'createOmicsRun'): TestData(tenant_perm=MANAGE_OMICS_RUNS, resource_perm=CREATE_OMICS_RUN), field_id('Mutation', 'createOrganization'): TestData( tenant_perm=MANAGE_ORGANIZATIONS, resource_ignore=IgnoreReason.NOTREQUIRED ), @@ -346,7 +426,7 @@ def __post_init__(self): tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED ), field_id('Mutation', 'createTableDataFilter'): TestData( - tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_DATASETS, resource_perm=CREATE_TABLE_DATA_FILTER ), field_id('Mutation', 'createTerm'): TestData( tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED @@ -355,7 +435,7 @@ def __post_init__(self): tenant_perm=MANAGE_WORKSHEETS, resource_ignore=IgnoreReason.NOTREQUIRED ), field_id('Mutation', 'deleteAttachedMetadataForm'): TestData( - tenant_ignore=IgnoreReason.BACKPORT, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_ignore=IgnoreReason.BACKPORT, resource_perm=ATTACH_METADATA_FORM ), field_id('Mutation', 'deleteCategory'): TestData( tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED @@ -363,26 +443,20 @@ def __post_init__(self): field_id('Mutation', 'deleteConnectionGroupPermission'): TestData( tenant_ignore=IgnoreReason.BACKPORT, resource_ignore=IgnoreReason.NOTREQUIRED ), - field_id('Mutation', 'deleteDashboard'): TestData( - tenant_perm=MANAGE_DASHBOARDS, resource_ignore=IgnoreReason.NOTREQUIRED - ), - field_id('Mutation', 'deleteDataPipeline'): TestData( - tenant_perm=MANAGE_PIPELINES, resource_ignore=IgnoreReason.NOTREQUIRED - ), + field_id('Mutation', 'deleteDashboard'): TestData(tenant_perm=MANAGE_DASHBOARDS, resource_perm=DELETE_DASHBOARD), + field_id('Mutation', 'deleteDataPipeline'): TestData(tenant_perm=MANAGE_PIPELINES, resource_perm=DELETE_PIPELINE), field_id('Mutation', 'deleteDataPipelineEnvironment'): TestData( tenant_perm=MANAGE_PIPELINES, resource_ignore=IgnoreReason.NOTREQUIRED ), - field_id('Mutation', 'deleteDataset'): TestData( - tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED - ), + field_id('Mutation', 'deleteDataset'): TestData(tenant_perm=MANAGE_DATASETS, resource_perm=DELETE_DATASET), field_id('Mutation', 'deleteDatasetStorageLocation'): TestData( - tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_DATASETS, resource_perm=DELETE_DATASET_FOLDER ), field_id('Mutation', 'deleteDatasetTable'): TestData( - tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_DATASETS, resource_perm=DELETE_DATASET_TABLE ), field_id('Mutation', 'deleteEnvironment'): TestData( - tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_ENVIRONMENTS, resource_perm=DELETE_ENVIRONMENT ), field_id('Mutation', 'deleteGlossary'): TestData( tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED @@ -396,9 +470,7 @@ def __post_init__(self): field_id('Mutation', 'deleteMetadataFormVersion'): TestData( tenant_perm=MANAGE_METADATA_FORMS, resource_ignore=IgnoreReason.NOTREQUIRED ), - field_id('Mutation', 'deleteNetwork'): TestData( - tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED - ), + field_id('Mutation', 'deleteNetwork'): TestData(tenant_perm=MANAGE_ENVIRONMENTS, resource_perm=DELETE_NETWORK), field_id('Mutation', 'deleteNotification'): TestData( tenant_ignore=IgnoreReason.APPSUPPORT, resource_ignore=IgnoreReason.NOTREQUIRED ), @@ -409,52 +481,44 @@ def __post_init__(self): tenant_ignore=IgnoreReason.BACKPORT, resource_ignore=IgnoreReason.NOTREQUIRED ), field_id('Mutation', 'deleteRedshiftDataset'): TestData( - tenant_perm=MANAGE_REDSHIFT_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_REDSHIFT_DATASETS, resource_perm=DELETE_REDSHIFT_DATASET ), field_id('Mutation', 'deleteRedshiftDatasetTable'): TestData( - tenant_perm=MANAGE_REDSHIFT_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_REDSHIFT_DATASETS, resource_perm=DELETE_REDSHIFT_DATASET_TABLE ), field_id('Mutation', 'deleteSagemakerNotebook'): TestData( - tenant_perm=MANAGE_NOTEBOOKS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_NOTEBOOKS, resource_perm=DELETE_NOTEBOOK ), field_id('Mutation', 'deleteSagemakerStudioUser'): TestData( - tenant_perm=MANAGE_SGMSTUDIO_USERS, resource_ignore=IgnoreReason.NOTREQUIRED - ), - field_id('Mutation', 'deleteShareObject'): TestData( - tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_SGMSTUDIO_USERS, resource_perm=DELETE_SGMSTUDIO_USER ), + field_id('Mutation', 'deleteShareObject'): TestData(tenant_perm=MANAGE_SHARES, resource_perm=DELETE_SHARE_OBJECT), field_id('Mutation', 'deleteTableDataFilter'): TestData( - tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_DATASETS, resource_perm=DELETE_TABLE_DATA_FILTER ), field_id('Mutation', 'deleteTerm'): TestData( tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED ), - field_id('Mutation', 'deleteWorksheet'): TestData( - tenant_perm=MANAGE_WORKSHEETS, resource_ignore=IgnoreReason.NOTREQUIRED - ), + field_id('Mutation', 'deleteWorksheet'): TestData(tenant_perm=MANAGE_WORKSHEETS, resource_perm=DELETE_WORKSHEET), field_id('Mutation', 'dismissTermAssociation'): TestData( tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED ), field_id('Mutation', 'enableDataSubscriptions'): TestData( - tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_ENVIRONMENTS, resource_perm=ENABLE_ENVIRONMENT_SUBSCRIPTIONS ), field_id('Mutation', 'generateDatasetAccessToken'): TestData( - tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED - ), - field_id('Mutation', 'importDashboard'): TestData( - tenant_perm=MANAGE_DASHBOARDS, resource_ignore=IgnoreReason.NOTREQUIRED - ), - field_id('Mutation', 'importDataset'): TestData( - tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_DATASETS, resource_perm=CREDENTIALS_DATASET ), + field_id('Mutation', 'importDashboard'): TestData(tenant_perm=MANAGE_DASHBOARDS, resource_perm=CREATE_DASHBOARD), + field_id('Mutation', 'importDataset'): TestData(tenant_perm=MANAGE_DATASETS, resource_perm=CREATE_DATASET), field_id('Mutation', 'importRedshiftDataset'): TestData( - tenant_perm=MANAGE_REDSHIFT_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_REDSHIFT_DATASETS, resource_perm=IMPORT_REDSHIFT_DATASET ), field_id('Mutation', 'inviteGroupOnEnvironment'): TestData( - tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_ENVIRONMENTS, resource_perm=INVITE_ENVIRONMENT_GROUP ), field_id('Mutation', 'inviteGroupToOrganization'): TestData( - tenant_perm=MANAGE_ORGANIZATIONS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_ORGANIZATIONS, resource_perm=INVITE_ORGANIZATION_GROUP ), field_id('Mutation', 'markNotificationAsRead'): TestData( tenant_ignore=IgnoreReason.APPSUPPORT, resource_ignore=IgnoreReason.NOTREQUIRED @@ -463,69 +527,55 @@ def __post_init__(self): tenant_ignore=IgnoreReason.APPSUPPORT, resource_ignore=IgnoreReason.NOTREQUIRED ), field_id('Mutation', 'reApplyItemsShareObject'): TestData( - tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_SHARES, resource_perm=APPROVE_SHARE_OBJECT ), field_id('Mutation', 'reApplyShareObjectItemsOnDataset'): TestData( - tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_DATASETS, resource_perm=UPDATE_DATASET ), field_id('Mutation', 'rejectDashboardShare'): TestData( tenant_perm=MANAGE_DASHBOARDS, resource_perm=SHARE_DASHBOARD ), - field_id('Mutation', 'rejectShareObject'): TestData( - tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED - ), + field_id('Mutation', 'rejectShareObject'): TestData(tenant_perm=MANAGE_SHARES, resource_perm=REJECT_SHARE_OBJECT), field_id('Mutation', 'removeConsumptionRoleFromEnvironment'): TestData( - tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_ENVIRONMENTS, resource_perm=REMOVE_ENVIRONMENT_CONSUMPTION_ROLE ), field_id('Mutation', 'removeGroupFromEnvironment'): TestData( - tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_ENVIRONMENTS, resource_perm=REMOVE_ENVIRONMENT_GROUP ), field_id('Mutation', 'removeGroupFromOrganization'): TestData( - tenant_perm=MANAGE_ORGANIZATIONS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_ORGANIZATIONS, resource_perm=REMOVE_ORGANIZATION_GROUP ), field_id('Mutation', 'removeShareItemFilter'): TestData( - tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED - ), - field_id('Mutation', 'removeSharedItem'): TestData( - tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_SHARES, resource_perm=APPROVE_SHARE_OBJECT ), + field_id('Mutation', 'removeSharedItem'): TestData(tenant_perm=MANAGE_SHARES, resource_perm=REMOVE_ITEM), field_id('Mutation', 'requestDashboardShare'): TestData( tenant_perm=MANAGE_DASHBOARDS, resource_ignore=IgnoreReason.NOTREQUIRED ), - field_id('Mutation', 'revokeItemsShareObject'): TestData( - tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED - ), + field_id('Mutation', 'revokeItemsShareObject'): TestData(tenant_perm=MANAGE_SHARES, resource_perm=GET_SHARE_OBJECT), field_id('Mutation', 'startDatasetProfilingRun'): TestData( - tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED - ), - field_id('Mutation', 'startGlueCrawler'): TestData( - tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_DATASETS, resource_perm=PROFILE_DATASET_TABLE ), + field_id('Mutation', 'startGlueCrawler'): TestData(tenant_perm=MANAGE_DATASETS, resource_perm=CRAWL_DATASET), field_id('Mutation', 'startMaintenanceWindow'): TestData( tenant_ignore=IgnoreReason.TENANT, resource_ignore=IgnoreReason.NOTREQUIRED ), field_id('Mutation', 'startReindexCatalog'): TestData( tenant_ignore=IgnoreReason.TENANT, resource_ignore=IgnoreReason.NOTREQUIRED ), - field_id('Mutation', 'startSagemakerNotebook'): TestData( - tenant_perm=MANAGE_NOTEBOOKS, resource_ignore=IgnoreReason.NOTREQUIRED - ), + field_id('Mutation', 'startSagemakerNotebook'): TestData(tenant_perm=MANAGE_NOTEBOOKS, resource_perm=GET_NOTEBOOK), field_id('Mutation', 'stopMaintenanceWindow'): TestData( tenant_ignore=IgnoreReason.TENANT, resource_ignore=IgnoreReason.NOTREQUIRED ), - field_id('Mutation', 'stopSagemakerNotebook'): TestData( - tenant_perm=MANAGE_NOTEBOOKS, resource_ignore=IgnoreReason.NOTREQUIRED - ), + field_id('Mutation', 'stopSagemakerNotebook'): TestData(tenant_perm=MANAGE_NOTEBOOKS, resource_perm=GET_NOTEBOOK), field_id('Mutation', 'submitShareExtension'): TestData( - tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED - ), - field_id('Mutation', 'submitShareObject'): TestData( - tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_SHARES, resource_perm=SUBMIT_SHARE_OBJECT ), + field_id('Mutation', 'submitShareObject'): TestData(tenant_perm=MANAGE_SHARES, resource_perm=SUBMIT_SHARE_OBJECT), field_id('Mutation', 'syncDatasetTableColumns'): TestData( - tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_DATASETS, resource_perm=UPDATE_DATASET_TABLE ), - field_id('Mutation', 'syncTables'): TestData(tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED), + field_id('Mutation', 'syncTables'): TestData(tenant_perm=MANAGE_DATASETS, resource_perm=SYNC_DATASET), field_id('Mutation', 'upVote'): TestData( tenant_ignore=IgnoreReason.APPSUPPORT, resource_ignore=IgnoreReason.NOTREQUIRED ), @@ -533,37 +583,33 @@ def __post_init__(self): tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED ), field_id('Mutation', 'updateConsumptionRole'): TestData( - tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED - ), - field_id('Mutation', 'updateDashboard'): TestData( - tenant_perm=MANAGE_DASHBOARDS, resource_ignore=IgnoreReason.NOTREQUIRED - ), - field_id('Mutation', 'updateDataPipeline'): TestData( - tenant_perm=MANAGE_PIPELINES, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_ENVIRONMENTS, resource_perm=REMOVE_ENVIRONMENT_CONSUMPTION_ROLE ), + field_id('Mutation', 'updateDashboard'): TestData(tenant_perm=MANAGE_DASHBOARDS, resource_perm=UPDATE_DASHBOARD), + field_id('Mutation', 'updateDataPipeline'): TestData(tenant_perm=MANAGE_PIPELINES, resource_perm=UPDATE_PIPELINE), field_id('Mutation', 'updateDataPipelineEnvironment'): TestData( - tenant_perm=MANAGE_PIPELINES, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_PIPELINES, resource_perm=UPDATE_PIPELINE ), field_id('Mutation', 'updateDataset'): TestData( tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED ), field_id('Mutation', 'updateDatasetStorageLocation'): TestData( - tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_DATASETS, resource_perm=UPDATE_DATASET_FOLDER ), field_id('Mutation', 'updateDatasetTable'): TestData( - tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_DATASETS, resource_perm=UPDATE_DATASET_TABLE ), field_id('Mutation', 'updateDatasetTableColumn'): TestData( - tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_DATASETS, resource_perm=UPDATE_DATASET_TABLE ), field_id('Mutation', 'updateEnvironment'): TestData( - tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_ENVIRONMENTS, resource_perm=UPDATE_ENVIRONMENT ), field_id('Mutation', 'updateGlossary'): TestData( tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED ), field_id('Mutation', 'updateGroupEnvironmentPermissions'): TestData( - tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_ENVIRONMENTS, resource_perm=UPDATE_ENVIRONMENT_GROUP ), field_id('Mutation', 'updateGroupTenantPermissions'): TestData( tenant_ignore=IgnoreReason.TENANT, resource_ignore=IgnoreReason.NOTREQUIRED @@ -572,34 +618,34 @@ def __post_init__(self): tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED ), field_id('Mutation', 'updateOrganization'): TestData( - tenant_perm=MANAGE_ORGANIZATIONS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_ORGANIZATIONS, resource_perm=UPDATE_ORGANIZATION ), field_id('Mutation', 'updateOrganizationGroup'): TestData( - tenant_perm=MANAGE_ORGANIZATIONS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_ORGANIZATIONS, resource_perm=INVITE_ORGANIZATION_GROUP ), field_id('Mutation', 'updateRedshiftDataset'): TestData( - tenant_perm=MANAGE_REDSHIFT_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_REDSHIFT_DATASETS, resource_perm=UPDATE_REDSHIFT_DATASET ), field_id('Mutation', 'updateRedshiftDatasetTable'): TestData( - tenant_perm=MANAGE_REDSHIFT_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_REDSHIFT_DATASETS, resource_perm=UPDATE_REDSHIFT_DATASET_TABLE ), field_id('Mutation', 'updateSSMParameter'): TestData( tenant_ignore=IgnoreReason.TENANT, resource_ignore=IgnoreReason.NOTREQUIRED ), field_id('Mutation', 'updateShareExpirationPeriod'): TestData( - tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_SHARES, resource_perm=SUBMIT_SHARE_OBJECT ), field_id('Mutation', 'updateShareExtensionReason'): TestData( - tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_SHARES, resource_perm=SUBMIT_SHARE_OBJECT ), field_id('Mutation', 'updateShareItemFilters'): TestData( tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED ), field_id('Mutation', 'updateShareRejectReason'): TestData( - tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_SHARES, resource_perm=REJECT_SHARE_OBJECT ), field_id('Mutation', 'updateShareRequestReason'): TestData( - tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_SHARES, resource_perm=SUBMIT_SHARE_OBJECT ), field_id('Mutation', 'updateStack'): TestData( tenant_perm=MANAGE_ENVIRONMENTS, resource_ignore=IgnoreReason.NOTREQUIRED @@ -607,15 +653,11 @@ def __post_init__(self): field_id('Mutation', 'updateTerm'): TestData( tenant_perm=MANAGE_GLOSSARIES, resource_ignore=IgnoreReason.NOTREQUIRED ), - field_id('Mutation', 'updateWorksheet'): TestData( - tenant_perm=MANAGE_WORKSHEETS, resource_ignore=IgnoreReason.NOTREQUIRED - ), + field_id('Mutation', 'updateWorksheet'): TestData(tenant_perm=MANAGE_WORKSHEETS, resource_perm=UPDATE_WORKSHEET), field_id('Mutation', 'verifyDatasetShareObjects'): TestData( - tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED - ), - field_id('Mutation', 'verifyItemsShareObject'): TestData( - tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_DATASETS, resource_perm=UPDATE_DATASET ), + field_id('Mutation', 'verifyItemsShareObject'): TestData(tenant_perm=MANAGE_SHARES, resource_perm=GET_SHARE_OBJECT), field_id('OmicsRun', 'environment'): TestData( resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED ), @@ -649,30 +691,22 @@ def __post_init__(self): field_id('Query', 'countUnreadNotifications'): TestData( resource_ignore=IgnoreReason.USERLIMITED, tenant_ignore=IgnoreReason.USERLIMITED ), - field_id('Query', 'countUpVotes'): TestData( - resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.PUBLIC - ), + field_id('Query', 'countUpVotes'): TestData(resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.PUBLIC), field_id('Query', 'generateEnvironmentAccessToken'): TestData( tenant_perm=MANAGE_ENVIRONMENTS, resource_perm=CREDENTIALS_ENVIRONMENT ), field_id('Query', 'getAttachedMetadataForm'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), - field_id('Query', 'getAuthorSession'): TestData( - resource_perm=CREATE_DASHBOARD, tenant_perm=MANAGE_DASHBOARDS - ), + field_id('Query', 'getAuthorSession'): TestData(resource_perm=CREATE_DASHBOARD, tenant_perm=MANAGE_DASHBOARDS), field_id('Query', 'getCDKExecPolicyPresignedUrl'): TestData( resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getConsumptionRolePolicies'): TestData( resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED ), - field_id('Query', 'getDashboard'): TestData( - resource_perm=GET_DASHBOARD, tenant_ignore=IgnoreReason.NOTREQUIRED - ), - field_id('Query', 'getDataPipeline'): TestData( - resource_perm=GET_PIPELINE, tenant_ignore=IgnoreReason.NOTREQUIRED - ), + field_id('Query', 'getDashboard'): TestData(resource_perm=GET_DASHBOARD, tenant_ignore=IgnoreReason.NOTREQUIRED), + field_id('Query', 'getDataPipeline'): TestData(resource_perm=GET_PIPELINE, tenant_ignore=IgnoreReason.NOTREQUIRED), field_id('Query', 'getDataPipelineCredsLinux'): TestData( resource_perm=CREDENTIALS_PIPELINE, tenant_perm=MANAGE_PIPELINES ), @@ -712,9 +746,7 @@ def __post_init__(self): field_id('Query', 'getFeed'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), - field_id('Query', 'getGlossary'): TestData( - resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.PUBLIC - ), + field_id('Query', 'getGlossary'): TestData(resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.PUBLIC), field_id('Query', 'getGroup'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), @@ -740,13 +772,13 @@ def __post_init__(self): resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getPivotRoleExternalId'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getPivotRoleName'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getPivotRolePresignedUrl'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getPlatformAuthorSession'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -758,13 +790,13 @@ def __post_init__(self): resource_perm=GET_DASHBOARD, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getRedshiftDataset'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_REDSHIFT_DATASET, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getRedshiftDatasetTable'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_REDSHIFT_DATASET_TABLE, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getRedshiftDatasetTableColumns'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_REDSHIFT_DATASET_TABLE, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getS3ConsumptionData'): TestData( resource_perm=GET_SHARE_OBJECT, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -779,14 +811,13 @@ def __post_init__(self): resource_perm=GET_SGMSTUDIO_USER, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getSagemakerStudioUserPresignedUrl'): TestData( - tenant_perm=MANAGE_SGMSTUDIO_USERS, resource_perm=SGMSTUDIO_USER_URL, + tenant_perm=MANAGE_SGMSTUDIO_USERS, + resource_perm=SGMSTUDIO_USER_URL, ), field_id('Query', 'getShareItemDataFilters'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED - ), - field_id('Query', 'getShareLogs'): TestData( - resource_ignore=IgnoreReason.CUSTOM, tenant_ignore=IgnoreReason.CUSTOM + resource_perm=GET_SHARE_OBJECT, tenant_ignore=IgnoreReason.NOTREQUIRED ), + field_id('Query', 'getShareLogs'): TestData(resource_ignore=IgnoreReason.CUSTOM, tenant_ignore=IgnoreReason.CUSTOM), field_id('Query', 'getShareObject'): TestData( resource_perm=GET_SHARE_OBJECT, tenant_ignore=IgnoreReason.NOTREQUIRED ), @@ -799,21 +830,13 @@ def __post_init__(self): field_id('Query', 'getSharedDatasetTables'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), # TODO Review - field_id('Query', 'getStack'): TestData( - resource_perm='getStack', tenant_ignore=IgnoreReason.NOTREQUIRED - ), - field_id('Query', 'getStackLogs'): TestData( - resource_perm='getStack', tenant_ignore=IgnoreReason.NOTREQUIRED - ), + field_id('Query', 'getStack'): TestData(resource_perm='getStack', tenant_ignore=IgnoreReason.NOTREQUIRED), + field_id('Query', 'getStackLogs'): TestData(resource_perm='getStack', tenant_ignore=IgnoreReason.NOTREQUIRED), field_id('Query', 'getTrustAccount'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), - field_id('Query', 'getVote'): TestData( - resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.PUBLIC - ), - field_id('Query', 'getWorksheet'): TestData( - resource_perm=GET_WORKSHEET, tenant_ignore=IgnoreReason.NOTREQUIRED - ), + field_id('Query', 'getVote'): TestData(resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.PUBLIC), + field_id('Query', 'getWorksheet'): TestData(resource_perm=GET_WORKSHEET, tenant_ignore=IgnoreReason.NOTREQUIRED), field_id('Query', 'listAllConsumptionRoles'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.USERLIMITED ), @@ -920,16 +943,16 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listRedshiftDatasetTables'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_REDSHIFT_DATASET, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listRedshiftSchemaDatasetTables'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_REDSHIFT_DATASET, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listRedshiftSchemaTables'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listS3DatasetsOwnedByEnvGroup'): TestData( - resource_ignore=IgnoreReason.USERLIMITED, tenant_ignore=IgnoreReason.USERLIMITED + resource_perm=LIST_ENVIRONMENT_DATASETS, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'listS3DatasetsSharedWithEnvGroup'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -941,13 +964,13 @@ def __post_init__(self): resource_ignore=IgnoreReason.USERLIMITED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'listSharedDatasetTableColumns'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_DATASET_TABLE, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listTableDataFilters'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=LIST_TABLE_DATA_FILTERS, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listTableDataFiltersByAttached'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_SHARE_OBJECT, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listTenantGroups'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.TENANT @@ -967,15 +990,11 @@ def __post_init__(self): field_id('Query', 'listWorksheets'): TestData( resource_ignore=IgnoreReason.USERLIMITED, tenant_ignore=IgnoreReason.USERLIMITED ), - field_id('Query', 'previewTable'): TestData( - resource_ignore=IgnoreReason.CUSTOM, tenant_ignore=IgnoreReason.CUSTOM - ), + field_id('Query', 'previewTable'): TestData(resource_ignore=IgnoreReason.CUSTOM, tenant_ignore=IgnoreReason.CUSTOM), field_id('Query', 'queryEnums'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), - field_id('Query', 'runAthenaSqlQuery'): TestData( - resource_perm=RUN_ATHENA_QUERY, tenant_perm=MANAGE_WORKSHEETS - ), + field_id('Query', 'runAthenaSqlQuery'): TestData(resource_perm=RUN_ATHENA_QUERY, tenant_perm=MANAGE_WORKSHEETS), field_id('Query', 'searchDashboards'): TestData( resource_ignore=IgnoreReason.USERLIMITED, tenant_ignore=IgnoreReason.USERLIMITED ), @@ -986,7 +1005,7 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('RedshiftDataset', 'connection'): TestData( - resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_REDSHIFT_CONNECTION, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('RedshiftDataset', 'environment'): TestData( resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -1001,19 +1020,19 @@ def __post_init__(self): resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('RedshiftDataset', 'upvotes'): TestData( - resource_ignore=IgnoreReason.APPSUPPORT, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_REDSHIFT_DATASET, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('RedshiftDataset', 'userRoleForDataset'): TestData( resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('RedshiftDatasetTable', 'dataset'): TestData( - resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_REDSHIFT_DATASET, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('RedshiftDatasetTable', 'terms'): TestData( resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('SagemakerNotebook', 'NotebookInstanceStatus'): TestData( - resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=GET_NOTEBOOK, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('SagemakerNotebook', 'environment'): TestData( resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -1191,7 +1210,7 @@ def test_unauthorized_tenant_permissions( @pytest.mark.parametrize('_type,field', ALL_PARAMS) def test_unauthorized_resource_permissions( mock_storage, - mock_check, + mock_check_resource, mock_perm_name, mock_session, _type, @@ -1216,10 +1235,11 @@ def test_unauthorized_resource_permissions( with suppress(Exception): field.resolver(**iargs) # TODO add support for asserting multiple calls in case a resolver checks multiple perms - mock_check.assert_any_call( - session=ANY, - resource_uri=ANY, - username=username, - groups=groups, - permission_name=expected_perm, - ) + if mock_check_resource.called: + mock_check_resource.assert_any_call( + session=ANY, + resource_uri=ANY, + username=username, + groups=groups, + permission_name=expected_perm, + ) From 724dd95ea12d757f3d947889f9a3292ca1c1bae1 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Mon, 2 Dec 2024 16:26:03 +0200 Subject: [PATCH 36/47] merge tests --- tests/test_tenant_unauthorized.py | 100 ++++++++++++------------------ 1 file changed, 38 insertions(+), 62 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index bdc450d38..97cb638e1 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -11,7 +11,6 @@ from dataall.base.api import bootstrap from dataall.base.context import RequestContext -from dataall.base.db.exceptions import TenantUnauthorized from dataall.core.permissions.services.environment_permissions import ( GET_ENVIRONMENT, LIST_ENVIRONMENT_CONSUMPTION_ROLES, @@ -66,8 +65,14 @@ MANAGE_SGMSTUDIO_USERS, SGMSTUDIO_USER_URL, DELETE_SGMSTUDIO_USER, + CREATE_SGMSTUDIO_USER, +) +from dataall.modules.notebooks.services.notebook_permissions import ( + GET_NOTEBOOK, + MANAGE_NOTEBOOKS, + DELETE_NOTEBOOK, + CREATE_NOTEBOOK, ) -from dataall.modules.notebooks.services.notebook_permissions import GET_NOTEBOOK, MANAGE_NOTEBOOKS, DELETE_NOTEBOOK from dataall.modules.omics.services.omics_permissions import MANAGE_OMICS_RUNS, CREATE_OMICS_RUN from dataall.modules.redshift_datasets.services.redshift_connection_permissions import GET_REDSHIFT_CONNECTION from dataall.modules.redshift_datasets.services.redshift_dataset_permissions import ( @@ -92,7 +97,6 @@ DELETE_DATASET, DELETE_DATASET_FOLDER, DELETE_TABLE_DATA_FILTER, - CREATE_DATASET, UPDATE_DATASET, PROFILE_DATASET_TABLE, CRAWL_DATASET, @@ -100,6 +104,8 @@ SYNC_DATASET, UPDATE_DATASET_FOLDER, LIST_TABLE_DATA_FILTERS, + CREATE_DATASET, + CREATE_DATASET_FOLDER, ) from dataall.modules.shares_base.services.share_permissions import ( MANAGE_SHARES, @@ -111,6 +117,7 @@ DELETE_SHARE_OBJECT, REJECT_SHARE_OBJECT, REMOVE_ITEM, + CREATE_SHARE_OBJECT, ) from dataall.modules.worksheets.services.worksheet_permissions import ( MANAGE_WORKSHEETS, @@ -384,11 +391,9 @@ def __post_init__(self): field_id('Mutation', 'createDataPipelineEnvironment'): TestData( tenant_perm=MANAGE_PIPELINES, resource_perm=CREATE_PIPELINE ), - field_id('Mutation', 'createDataset'): TestData( - tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED - ), + field_id('Mutation', 'createDataset'): TestData(tenant_perm=MANAGE_DATASETS, resource_perm=CREATE_DATASET), field_id('Mutation', 'createDatasetStorageLocation'): TestData( - tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_DATASETS, resource_perm=CREATE_DATASET_FOLDER ), field_id('Mutation', 'createEnvironment'): TestData( tenant_perm=MANAGE_ENVIRONMENTS, resource_perm=LINK_ENVIRONMENT @@ -417,14 +422,12 @@ def __post_init__(self): tenant_ignore=IgnoreReason.BACKPORT, resource_ignore=IgnoreReason.NOTREQUIRED ), field_id('Mutation', 'createSagemakerNotebook'): TestData( - tenant_perm=MANAGE_NOTEBOOKS, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_NOTEBOOKS, resource_perm=CREATE_NOTEBOOK ), field_id('Mutation', 'createSagemakerStudioUser'): TestData( - tenant_perm=MANAGE_SGMSTUDIO_USERS, resource_ignore=IgnoreReason.NOTREQUIRED - ), - field_id('Mutation', 'createShareObject'): TestData( - tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_SGMSTUDIO_USERS, resource_perm=CREATE_SGMSTUDIO_USER ), + field_id('Mutation', 'createShareObject'): TestData(tenant_perm=MANAGE_SHARES, resource_perm=CREATE_SHARE_OBJECT), field_id('Mutation', 'createTableDataFilter'): TestData( tenant_perm=MANAGE_DATASETS, resource_perm=CREATE_TABLE_DATA_FILTER ), @@ -590,9 +593,7 @@ def __post_init__(self): field_id('Mutation', 'updateDataPipelineEnvironment'): TestData( tenant_perm=MANAGE_PIPELINES, resource_perm=UPDATE_PIPELINE ), - field_id('Mutation', 'updateDataset'): TestData( - tenant_perm=MANAGE_DATASETS, resource_ignore=IgnoreReason.NOTREQUIRED - ), + field_id('Mutation', 'updateDataset'): TestData(tenant_perm=MANAGE_DATASETS, resource_perm=UPDATE_DATASET), field_id('Mutation', 'updateDatasetStorageLocation'): TestData( tenant_perm=MANAGE_DATASETS, resource_perm=UPDATE_DATASET_FOLDER ), @@ -639,7 +640,7 @@ def __post_init__(self): tenant_perm=MANAGE_SHARES, resource_perm=SUBMIT_SHARE_OBJECT ), field_id('Mutation', 'updateShareItemFilters'): TestData( - tenant_perm=MANAGE_SHARES, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_SHARES, resource_perm=APPROVE_SHARE_OBJECT ), field_id('Mutation', 'updateShareRejectReason'): TestData( tenant_perm=MANAGE_SHARES, resource_perm=REJECT_SHARE_OBJECT @@ -1147,7 +1148,7 @@ def test_all_resolvers_have_test_data(): ).contains_only(*EXPECTED_RESOLVERS.keys()) -ALL_PARAMS = [pytest.param(_type, field, id=field_id(_type.name, field.name)) for _type, field in ALL_RESOLVERS] +ALL_PARAMS = [pytest.param(field, id=field_id(_type.name, field.name)) for _type, field in ALL_RESOLVERS] @pytest.fixture(scope='function') @@ -1168,17 +1169,20 @@ def mock_input_validation(mocker): mocker.patch('dataall.modules.shares_base.api.resolvers.RequestValidator', MagicMock()) -@pytest.mark.parametrize('_type,field', ALL_PARAMS) +@pytest.mark.parametrize('field', ALL_PARAMS) @patch('dataall.base.context._request_storage') @patch('dataall.core.permissions.services.resource_policy_service.ResourcePolicyService.check_user_resource_permission') @patch('dataall.core.permissions.services.group_policy_service.GroupPolicyService.check_group_environment_permission') @patch('dataall.core.permissions.services.tenant_policy_service.TenantPolicyService.check_user_tenant_permission') -def test_unauthorized_tenant_permissions( - mock_tenant_check, +@patch('dataall.core.stacks.db.target_type_repositories.TargetType.get_resource_read_permission_name') +@patch('dataall.base.aws.sts.SessionHelper.remote_session') +def test_permissions( + remote_session, + mock_perm_name, + mock_check_tenant, mock_check_group, mock_check_resource, mock_storage, - _type, field, request, mock_input_validation, @@ -1186,43 +1190,8 @@ def test_unauthorized_tenant_permissions( fid = request.node.callspec.id tdata = EXPECTED_RESOLVERS[fid] msg = f'{fid} -> {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' - expected_perm = tdata.tenant_perm - if not expected_perm: - pytest.skip(msg + f' Reason: {tdata.tenant_ignore.value}') - logging.info(msg) - - assert_that(field.resolver).is_not_none() - username = 'ausername' - groups = ['agroup'] - mock_storage.context = RequestContext(MagicMock(), username, groups, 'auserid') - mock_tenant_check.side_effect = TenantUnauthorized(username, 'test_action', 'test_tenant') - iargs = {arg: MagicMock() for arg in inspect.signature(field.resolver).parameters.keys()} - assert_that(field.resolver).raises(TenantUnauthorized).when_called_with(**iargs).contains('UnauthorizedOperation') - mock_tenant_check.assert_called_once_with( - session=ANY, username=username, groups=groups, tenant_name=ANY, permission_name=expected_perm - ) - - -@patch('dataall.base.aws.sts.SessionHelper.remote_session') -@patch('dataall.core.stacks.db.target_type_repositories.TargetType.get_resource_read_permission_name') -@patch('dataall.core.permissions.services.resource_policy_service.ResourcePolicyService.check_user_resource_permission') -@patch('dataall.base.context._request_storage') -@pytest.mark.parametrize('_type,field', ALL_PARAMS) -def test_unauthorized_resource_permissions( - mock_storage, - mock_check_resource, - mock_perm_name, - mock_session, - _type, - field, - request, -): - fid = request.node.callspec.id - tdata = EXPECTED_RESOLVERS[fid] - msg = f'{fid} -> {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' - expected_perm = tdata.resource_perm - if not expected_perm: - pytest.skip(msg + f' Reason: {tdata.resource_ignore.value}') + if not any([tdata.resource_perm, tdata.tenant_perm]): + pytest.skip(msg + f' Reason: {tdata.tenant_ignore.value or tdata.resource_ignore.value}') logging.info(msg) assert_that(field.resolver).is_not_none() @@ -1230,16 +1199,23 @@ def test_unauthorized_resource_permissions( groups = ['agroup'] mock_storage.context = RequestContext(MagicMock(), username, groups, 'auserid') mock_storage.context.db_engine.scoped_session().__enter__().query().filter().all.return_value = [MagicMock()] - mock_perm_name.return_value = expected_perm + mock_perm_name.return_value = tdata.resource_perm iargs = {arg: MagicMock() for arg in inspect.signature(field.resolver).parameters.keys()} with suppress(Exception): field.resolver(**iargs) - # TODO add support for asserting multiple calls in case a resolver checks multiple perms - if mock_check_resource.called: + if tdata.tenant_perm: + mock_check_tenant.assert_any_call( + session=ANY, + username=username, + groups=groups, + tenant_name=ANY, + permission_name=tdata.tenant_perm, + ) + if tdata.resource_perm: mock_check_resource.assert_any_call( session=ANY, resource_uri=ANY, username=username, groups=groups, - permission_name=expected_perm, + permission_name=tdata.resource_perm, ) From 0bd0a90be5a1c219f0634b6572361aea67e1b5f7 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Mon, 2 Dec 2024 16:53:19 +0200 Subject: [PATCH 37/47] mock aws calls for speed --- tests/test_tenant_unauthorized.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index 97cb638e1..6be293931 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -1167,6 +1167,10 @@ def mock_input_validation(mocker): return_value='MANAGE_ENVIRONMENTS', ) mocker.patch('dataall.modules.shares_base.api.resolvers.RequestValidator', MagicMock()) + # mock aws calls for speed + mocker.patch('dataall.base.aws.sts.SessionHelper._get_parameter_value') + mocker.patch('dataall.base.aws.sts.SessionHelper.remote_session') + mocker.patch('boto3.client').side_effect = RuntimeError('mocked boto3 client') @pytest.mark.parametrize('field', ALL_PARAMS) @@ -1175,9 +1179,7 @@ def mock_input_validation(mocker): @patch('dataall.core.permissions.services.group_policy_service.GroupPolicyService.check_group_environment_permission') @patch('dataall.core.permissions.services.tenant_policy_service.TenantPolicyService.check_user_tenant_permission') @patch('dataall.core.stacks.db.target_type_repositories.TargetType.get_resource_read_permission_name') -@patch('dataall.base.aws.sts.SessionHelper.remote_session') def test_permissions( - remote_session, mock_perm_name, mock_check_tenant, mock_check_group, From 6b316c0a641862a33231328ed9cebf4b1e6f6021 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Mon, 2 Dec 2024 17:01:26 +0200 Subject: [PATCH 38/47] add deleteDataPipelineEnvironment perm --- .../modules/datapipelines/services/datapipelines_service.py | 1 + tests/test_tenant_unauthorized.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/dataall/modules/datapipelines/services/datapipelines_service.py b/backend/dataall/modules/datapipelines/services/datapipelines_service.py index de277d20d..08dc46986 100644 --- a/backend/dataall/modules/datapipelines/services/datapipelines_service.py +++ b/backend/dataall/modules/datapipelines/services/datapipelines_service.py @@ -255,6 +255,7 @@ def _delete_repository(target_uri, accountid, cdk_role_arn, region, repo_name): @staticmethod @TenantPolicyService.has_tenant_permission(MANAGE_PIPELINES) + @ResourcePolicyService.has_resource_permission(UPDATE_PIPELINE, param_name='envPipelineUri') def delete_pipeline_environment(envPipelineUri: str): with _session() as session: DatapipelinesRepository.delete_pipeline_environment(session=session, envPipelineUri=envPipelineUri) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index 6be293931..0555e2aa8 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -449,7 +449,7 @@ def __post_init__(self): field_id('Mutation', 'deleteDashboard'): TestData(tenant_perm=MANAGE_DASHBOARDS, resource_perm=DELETE_DASHBOARD), field_id('Mutation', 'deleteDataPipeline'): TestData(tenant_perm=MANAGE_PIPELINES, resource_perm=DELETE_PIPELINE), field_id('Mutation', 'deleteDataPipelineEnvironment'): TestData( - tenant_perm=MANAGE_PIPELINES, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_perm=MANAGE_PIPELINES, resource_perm=UPDATE_PIPELINE ), field_id('Mutation', 'deleteDataset'): TestData(tenant_perm=MANAGE_DATASETS, resource_perm=DELETE_DATASET), field_id('Mutation', 'deleteDatasetStorageLocation'): TestData( From afec8ebd20f36e4cd4b148a928f24ac4a33d8a11 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Mon, 2 Dec 2024 17:35:59 +0200 Subject: [PATCH 39/47] workaround inf loop --- tests/test_tenant_unauthorized.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index 0555e2aa8..a9b37477b 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -1167,6 +1167,10 @@ def mock_input_validation(mocker): return_value='MANAGE_ENVIRONMENTS', ) mocker.patch('dataall.modules.shares_base.api.resolvers.RequestValidator', MagicMock()) + # workaround infinite loop when checking GlossaryResourceAccess.is_owner() + mocker.patch( + 'dataall.modules.catalog.db.glossary_repositories.GlossaryRepository.get_node' + ).side_effect = RuntimeError # mock aws calls for speed mocker.patch('dataall.base.aws.sts.SessionHelper._get_parameter_value') mocker.patch('dataall.base.aws.sts.SessionHelper.remote_session') From 754f51ae4042bd2f1d04b806fd31af4a29ad7ac5 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Tue, 3 Dec 2024 10:50:43 +0200 Subject: [PATCH 40/47] call get_organization --- .../core/organizations/services/organization_service.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/backend/dataall/core/organizations/services/organization_service.py b/backend/dataall/core/organizations/services/organization_service.py index 798480dc0..cbc81a1ce 100644 --- a/backend/dataall/core/organizations/services/organization_service.py +++ b/backend/dataall/core/organizations/services/organization_service.py @@ -305,14 +305,7 @@ def resolve_organization_by_env(uri): context = get_context() with context.db_engine.scoped_session() as session: env = EnvironmentRepository.get_environment_by_uri(session, uri) - ResourcePolicyService.check_user_resource_permission( - session=session, - username=get_context().username, - groups=get_context().groups, - resource_uri=env.organizationUri, - permission_name=GET_ORGANIZATION, - ) - return OrganizationRepository.find_organization_by_uri(session, env.organizationUri) + return OrganizationService.get_organization(uri=env.organizationUri) @staticmethod @ResourcePolicyService.has_resource_permission(GET_ORGANIZATION) From e9469f96993c663f19a2659e7b43904203c283f1 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Tue, 3 Dec 2024 11:00:54 +0200 Subject: [PATCH 41/47] introduce dataset_service.py::find_dataset --- .../api/storage_location/resolvers.py | 19 ++++--------------- .../s3_datasets/services/dataset_service.py | 5 +++++ 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/backend/dataall/modules/s3_datasets/api/storage_location/resolvers.py b/backend/dataall/modules/s3_datasets/api/storage_location/resolvers.py index a34e0b259..39aa2d8cf 100644 --- a/backend/dataall/modules/s3_datasets/api/storage_location/resolvers.py +++ b/backend/dataall/modules/s3_datasets/api/storage_location/resolvers.py @@ -1,12 +1,10 @@ from dataall.base.api.context import Context -from dataall.base.context import get_context -from dataall.core.permissions.services.resource_policy_service import ResourcePolicyService -from dataall.modules.catalog.db.glossary_repositories import GlossaryRepository from dataall.base.db.exceptions import RequiredParameter from dataall.base.feature_toggle_checker import is_feature_enabled +from dataall.modules.catalog.db.glossary_repositories import GlossaryRepository +from dataall.modules.s3_datasets.db.dataset_models import DatasetStorageLocation from dataall.modules.s3_datasets.services.dataset_location_service import DatasetLocationService -from dataall.modules.s3_datasets.db.dataset_models import DatasetStorageLocation, S3Dataset -from dataall.modules.s3_datasets.services.dataset_permissions import GET_DATASET +from dataall.modules.s3_datasets.services.dataset_service import DatasetService def _validate_input(input: dict): @@ -49,16 +47,7 @@ def remove_storage_location(context, source, locationUri: str = None): def resolve_dataset(context, source: DatasetStorageLocation, **kwargs): if not source: return None - with context.engine.scoped_session() as session: - ResourcePolicyService.check_user_resource_permission( - session=session, - username=get_context().username, - groups=get_context().groups, - resource_uri=source.datasetUri, - permission_name=GET_DATASET, - ) - d = session.query(S3Dataset).get(source.datasetUri) - return d + return DatasetService.find_dataset(uri=source.datasetUri) def resolve_glossary_terms(context: Context, source: DatasetStorageLocation, **kwargs): diff --git a/backend/dataall/modules/s3_datasets/services/dataset_service.py b/backend/dataall/modules/s3_datasets/services/dataset_service.py index 226645318..6d3010bf4 100644 --- a/backend/dataall/modules/s3_datasets/services/dataset_service.py +++ b/backend/dataall/modules/s3_datasets/services/dataset_service.py @@ -243,6 +243,11 @@ def get_dataset(uri): dataset.userRoleForDataset = DatasetRole.Admin.value return dataset + @classmethod + @ResourcePolicyService.has_resource_permission(GET_DATASET) + def find_dataset(cls, uri): + return DatasetService.get_dataset(uri) + @staticmethod @TenantPolicyService.has_tenant_permission(MANAGE_DATASETS) @ResourcePolicyService.has_resource_permission(CREDENTIALS_DATASET) From fd355b60d82019647c8487dc1b229316f14da083 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Tue, 3 Dec 2024 12:23:01 +0200 Subject: [PATCH 42/47] split into 2 tests --- tests/test_tenant_unauthorized.py | 124 +++++++++++++++++++----------- 1 file changed, 81 insertions(+), 43 deletions(-) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_tenant_unauthorized.py index a9b37477b..cf760af85 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_tenant_unauthorized.py @@ -3,7 +3,7 @@ from contextlib import suppress from dataclasses import dataclass from enum import Enum -from typing import Mapping +from typing import Mapping, Tuple from unittest.mock import MagicMock, patch, ANY import pytest @@ -153,6 +153,15 @@ class TestData: tenant_ignore: IgnoreReason = None tenant_perm: str = None + def get_perm(self, _type: str) -> IgnoreReason: + return getattr(self, f'{_type}_perm') + + def get_ignore(self, _type) -> str: + return getattr(self, f'{_type}_ignore') + + def get(self, _type) -> Tuple[IgnoreReason, str]: + return self.get_perm(_type), self.get_ignore(_type) + def __post_init__(self): if not bool(self.resource_perm) ^ bool(self.resource_ignore): raise ValueError('Either resource_perm or resource_ignore must be set') @@ -1139,18 +1148,6 @@ def __post_init__(self): ALL_RESOLVERS = {(_type, field) for _type in bootstrap().types for field in _type.fields if field.resolver} -def test_all_resolvers_have_test_data(): - """ - ensure that all EXPECTED_RESOURCES_PERMS have a corresponding query (to avoid stale entries) and vice versa - """ - assert_that([field_id(res[0].name, res[1].name) for res in ALL_RESOLVERS]).described_as( - 'stale or missing EXPECTED_RESOURCE_PERMS detected' - ).contains_only(*EXPECTED_RESOLVERS.keys()) - - -ALL_PARAMS = [pytest.param(field, id=field_id(_type.name, field.name)) for _type, field in ALL_RESOLVERS] - - @pytest.fixture(scope='function') def mock_input_validation(mocker): mocker.patch('dataall.modules.mlstudio.api.resolvers.RequestValidator', MagicMock()) @@ -1177,51 +1174,92 @@ def mock_input_validation(mocker): mocker.patch('boto3.client').side_effect = RuntimeError('mocked boto3 client') -@pytest.mark.parametrize('field', ALL_PARAMS) +def test_all_resolvers_have_test_data(): + """ + ensure that all EXPECTED_RESOURCES_PERMS have a corresponding query (to avoid stale entries) and vice versa + """ + assert_that([field_id(res[0].name, res[1].name) for res in ALL_RESOLVERS]).described_as( + 'stale or missing EXPECTED_RESOURCE_PERMS detected' + ).contains_only(*EXPECTED_RESOLVERS.keys()) + + +@pytest.mark.parametrize( + 'field', [pytest.param(field, id=field_id(_type.name, field.name)) for _type, field in ALL_RESOLVERS] +) @patch('dataall.base.context._request_storage') @patch('dataall.core.permissions.services.resource_policy_service.ResourcePolicyService.check_user_resource_permission') @patch('dataall.core.permissions.services.group_policy_service.GroupPolicyService.check_group_environment_permission') @patch('dataall.core.permissions.services.tenant_policy_service.TenantPolicyService.check_user_tenant_permission') @patch('dataall.core.stacks.db.target_type_repositories.TargetType.get_resource_read_permission_name') -def test_permissions( - mock_perm_name, - mock_check_tenant, - mock_check_group, - mock_check_resource, - mock_storage, - field, - request, - mock_input_validation, -): - fid = request.node.callspec.id - tdata = EXPECTED_RESOLVERS[fid] - msg = f'{fid} -> {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' - if not any([tdata.resource_perm, tdata.tenant_perm]): - pytest.skip(msg + f' Reason: {tdata.tenant_ignore.value or tdata.resource_ignore.value}') - logging.info(msg) +class TestGroup: + def _setup(self, field, request, mock_storage, mock_perm_name, permission_type): + """Common setup for both tenant and resource permission tests""" + fid = request.node.callspec.id + perm, reason = EXPECTED_RESOLVERS[fid].get(permission_type) + msg = f'{fid} -> {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' + + if not perm: + pytest.skip(msg + f' Reason: {reason.value}') + logging.info(msg) + + assert_that(field.resolver).is_not_none() + + # Setup mock context + username = 'ausername' + groups = ['agroup'] + mock_storage.context = RequestContext(MagicMock(), username, groups, 'auserid') + mock_storage.context.db_engine.scoped_session().__enter__().query().filter().all.return_value = [MagicMock()] + mock_perm_name.return_value = perm + + return username, groups, perm + + def _execute_resolver(self, field): + iargs = {arg: MagicMock() for arg in inspect.signature(field.resolver).parameters.keys()} + with suppress(Exception): + field.resolver(**iargs) + + def test_tenant_permissions( + self, + mock_perm_name, + mock_check_tenant, + mock_check_group, + mock_check_resource, + mock_storage, + field, + request, + mock_input_validation, + ): + username, groups, perm = self._setup(field, request, mock_storage, mock_perm_name, 'tenant') + + self._execute_resolver(field) - assert_that(field.resolver).is_not_none() - username = 'ausername' - groups = ['agroup'] - mock_storage.context = RequestContext(MagicMock(), username, groups, 'auserid') - mock_storage.context.db_engine.scoped_session().__enter__().query().filter().all.return_value = [MagicMock()] - mock_perm_name.return_value = tdata.resource_perm - iargs = {arg: MagicMock() for arg in inspect.signature(field.resolver).parameters.keys()} - with suppress(Exception): - field.resolver(**iargs) - if tdata.tenant_perm: mock_check_tenant.assert_any_call( session=ANY, username=username, groups=groups, tenant_name=ANY, - permission_name=tdata.tenant_perm, + permission_name=perm, ) - if tdata.resource_perm: + + def test_resource_permissions( + self, + mock_perm_name, + mock_check_tenant, + mock_check_group, + mock_check_resource, + mock_storage, + field, + request, + mock_input_validation, + ): + username, groups, perm = self._setup(field, request, mock_storage, mock_perm_name, 'resource') + + self._execute_resolver(field) + mock_check_resource.assert_any_call( session=ANY, resource_uri=ANY, username=username, groups=groups, - permission_name=tdata.resource_perm, + permission_name=perm, ) From 28006c020b37fee9e623f3087435b20b1c139d6f Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Tue, 3 Dec 2024 15:14:53 +0200 Subject: [PATCH 43/47] add unchecked test and parametrize based on type --- ...nt_unauthorized.py => test_permissions.py} | 120 +++++++----------- 1 file changed, 49 insertions(+), 71 deletions(-) rename tests/{test_tenant_unauthorized.py => test_permissions.py} (96%) diff --git a/tests/test_tenant_unauthorized.py b/tests/test_permissions.py similarity index 96% rename from tests/test_tenant_unauthorized.py rename to tests/test_permissions.py index cf760af85..23db76ea0 100644 --- a/tests/test_tenant_unauthorized.py +++ b/tests/test_permissions.py @@ -710,7 +710,7 @@ def __post_init__(self): ), field_id('Query', 'getAuthorSession'): TestData(resource_perm=CREATE_DASHBOARD, tenant_perm=MANAGE_DASHBOARDS), field_id('Query', 'getCDKExecPolicyPresignedUrl'): TestData( - resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=LINK_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getConsumptionRolePolicies'): TestData( resource_perm=GET_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -782,16 +782,13 @@ def __post_init__(self): resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getPivotRoleExternalId'): TestData( - resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=LINK_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getPivotRoleName'): TestData( - resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=LINK_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getPivotRolePresignedUrl'): TestData( - resource_perm=GET_ORGANIZATION, tenant_ignore=IgnoreReason.NOTREQUIRED - ), - field_id('Query', 'getPlatformAuthorSession'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=LINK_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getPlatformReaderSession'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -843,7 +840,7 @@ def __post_init__(self): field_id('Query', 'getStack'): TestData(resource_perm='getStack', tenant_ignore=IgnoreReason.NOTREQUIRED), field_id('Query', 'getStackLogs'): TestData(resource_perm='getStack', tenant_ignore=IgnoreReason.NOTREQUIRED), field_id('Query', 'getTrustAccount'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=LINK_ENVIRONMENT, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'getVote'): TestData(resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.PUBLIC), field_id('Query', 'getWorksheet'): TestData(resource_perm=GET_WORKSHEET, tenant_ignore=IgnoreReason.NOTREQUIRED), @@ -965,7 +962,7 @@ def __post_init__(self): resource_perm=LIST_ENVIRONMENT_DATASETS, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'listS3DatasetsSharedWithEnvGroup'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_perm=LIST_ENVIRONMENT_DATASETS, tenant_ignore=IgnoreReason.NOTREQUIRED ), # TODO Review field_id('Query', 'listSagemakerNotebooks'): TestData( resource_ignore=IgnoreReason.USERLIMITED, tenant_ignore=IgnoreReason.USERLIMITED @@ -1174,36 +1171,43 @@ def mock_input_validation(mocker): mocker.patch('boto3.client').side_effect = RuntimeError('mocked boto3 client') +ALL_PARAMS = [pytest.param(field, id=field_id(_type.name, field.name)) for _type, field in ALL_RESOLVERS] + + def test_all_resolvers_have_test_data(): """ ensure that all EXPECTED_RESOURCES_PERMS have a corresponding query (to avoid stale entries) and vice versa """ - assert_that([field_id(res[0].name, res[1].name) for res in ALL_RESOLVERS]).described_as( + assert_that(ALL_PARAMS).extracting(2).described_as( 'stale or missing EXPECTED_RESOURCE_PERMS detected' ).contains_only(*EXPECTED_RESOLVERS.keys()) -@pytest.mark.parametrize( - 'field', [pytest.param(field, id=field_id(_type.name, field.name)) for _type, field in ALL_RESOLVERS] -) +@pytest.mark.parametrize('field', ALL_PARAMS) @patch('dataall.base.context._request_storage') @patch('dataall.core.permissions.services.resource_policy_service.ResourcePolicyService.check_user_resource_permission') @patch('dataall.core.permissions.services.group_policy_service.GroupPolicyService.check_group_environment_permission') @patch('dataall.core.permissions.services.tenant_policy_service.TenantPolicyService.check_user_tenant_permission') @patch('dataall.core.stacks.db.target_type_repositories.TargetType.get_resource_read_permission_name') -class TestGroup: - def _setup(self, field, request, mock_storage, mock_perm_name, permission_type): - """Common setup for both tenant and resource permission tests""" - fid = request.node.callspec.id - perm, reason = EXPECTED_RESOLVERS[fid].get(permission_type) +class TestPermissions: + @pytest.mark.parametrize('perm_type', ['resource', 'tenant']) + def test_permissions( + self, + mock_perm_name, + mock_check_tenant, + mock_check_group, + mock_check_resource, + mock_storage, + field, + perm_type, + request, + mock_input_validation, + ): + fid = request.node.callspec.id.split('-')[-1] + perm, reason = EXPECTED_RESOLVERS[fid].get(perm_type) msg = f'{fid} -> {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' - - if not perm: - pytest.skip(msg + f' Reason: {reason.value}') logging.info(msg) - assert_that(field.resolver).is_not_none() - # Setup mock context username = 'ausername' groups = ['agroup'] @@ -1211,55 +1215,29 @@ def _setup(self, field, request, mock_storage, mock_perm_name, permission_type): mock_storage.context.db_engine.scoped_session().__enter__().query().filter().all.return_value = [MagicMock()] mock_perm_name.return_value = perm - return username, groups, perm - - def _execute_resolver(self, field): iargs = {arg: MagicMock() for arg in inspect.signature(field.resolver).parameters.keys()} with suppress(Exception): field.resolver(**iargs) - def test_tenant_permissions( - self, - mock_perm_name, - mock_check_tenant, - mock_check_group, - mock_check_resource, - mock_storage, - field, - request, - mock_input_validation, - ): - username, groups, perm = self._setup(field, request, mock_storage, mock_perm_name, 'tenant') - - self._execute_resolver(field) - - mock_check_tenant.assert_any_call( - session=ANY, - username=username, - groups=groups, - tenant_name=ANY, - permission_name=perm, - ) - - def test_resource_permissions( - self, - mock_perm_name, - mock_check_tenant, - mock_check_group, - mock_check_resource, - mock_storage, - field, - request, - mock_input_validation, - ): - username, groups, perm = self._setup(field, request, mock_storage, mock_perm_name, 'resource') - - self._execute_resolver(field) - - mock_check_resource.assert_any_call( - session=ANY, - resource_uri=ANY, - username=username, - groups=groups, - permission_name=perm, - ) + if not perm: + # if no expected permission is defined, we expect the check to not be called + locals()[f'mock_check_{perm_type}'].assert_not_called() + pytest.skip(msg + f' Reason: {reason.value}') + elif perm_type == 'resource': + mock_check_resource.assert_any_call( + session=ANY, + resource_uri=ANY, + username=username, + groups=groups, + permission_name=perm, + ) + elif perm_type == 'tenant': + mock_check_tenant.assert_any_call( + session=ANY, + username=username, + groups=groups, + tenant_name=ANY, + permission_name=perm, + ) + else: + raise ValueError(f'unknown permission type {perm_type}') From e2e26b56b7eccdbb69beaa3567dd56b627f899e5 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Tue, 3 Dec 2024 16:08:42 +0200 Subject: [PATCH 44/47] fix semgrep --- tests/test_permissions.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/test_permissions.py b/tests/test_permissions.py index 23db76ea0..944231dee 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -1219,9 +1219,8 @@ def test_permissions( with suppress(Exception): field.resolver(**iargs) - if not perm: - # if no expected permission is defined, we expect the check to not be called - locals()[f'mock_check_{perm_type}'].assert_not_called() + if not perm: # if no expected permission is defined, we expect the check to not be called + locals()[f'mock_check_{perm_type}'].assert_not_called() # nosemgrep pytest.skip(msg + f' Reason: {reason.value}') elif perm_type == 'resource': mock_check_resource.assert_any_call( From d88540a49f21db41687a20c14f8a999332ae8601 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Tue, 3 Dec 2024 16:19:14 +0200 Subject: [PATCH 45/47] simplify --- tests/test_permissions.py | 96 +++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 49 deletions(-) diff --git a/tests/test_permissions.py b/tests/test_permissions.py index 944231dee..fff788afc 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -1184,59 +1184,57 @@ def test_all_resolvers_have_test_data(): @pytest.mark.parametrize('field', ALL_PARAMS) +@pytest.mark.parametrize('perm_type', ['resource', 'tenant']) @patch('dataall.base.context._request_storage') @patch('dataall.core.permissions.services.resource_policy_service.ResourcePolicyService.check_user_resource_permission') @patch('dataall.core.permissions.services.group_policy_service.GroupPolicyService.check_group_environment_permission') @patch('dataall.core.permissions.services.tenant_policy_service.TenantPolicyService.check_user_tenant_permission') @patch('dataall.core.stacks.db.target_type_repositories.TargetType.get_resource_read_permission_name') -class TestPermissions: - @pytest.mark.parametrize('perm_type', ['resource', 'tenant']) - def test_permissions( - self, - mock_perm_name, - mock_check_tenant, - mock_check_group, - mock_check_resource, - mock_storage, - field, - perm_type, - request, - mock_input_validation, - ): - fid = request.node.callspec.id.split('-')[-1] - perm, reason = EXPECTED_RESOLVERS[fid].get(perm_type) - msg = f'{fid} -> {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' - logging.info(msg) - assert_that(field.resolver).is_not_none() - # Setup mock context - username = 'ausername' - groups = ['agroup'] - mock_storage.context = RequestContext(MagicMock(), username, groups, 'auserid') - mock_storage.context.db_engine.scoped_session().__enter__().query().filter().all.return_value = [MagicMock()] - mock_perm_name.return_value = perm +def test_permissions( + mock_perm_name, + mock_check_tenant, + mock_check_group, + mock_check_resource, + mock_storage, + field, + perm_type, + request, + mock_input_validation, +): + fid = request.node.callspec.id.split('-')[-1] + perm, reason = EXPECTED_RESOLVERS[fid].get(perm_type) + msg = f'{fid} -> {field.resolver.__code__.co_filename}:{field.resolver.__code__.co_firstlineno}' + logging.info(msg) + assert_that(field.resolver).is_not_none() + # Setup mock context + username = 'ausername' + groups = ['agroup'] + mock_storage.context = RequestContext(MagicMock(), username, groups, 'auserid') + mock_storage.context.db_engine.scoped_session().__enter__().query().filter().all.return_value = [MagicMock()] + mock_perm_name.return_value = perm - iargs = {arg: MagicMock() for arg in inspect.signature(field.resolver).parameters.keys()} - with suppress(Exception): - field.resolver(**iargs) + iargs = {arg: MagicMock() for arg in inspect.signature(field.resolver).parameters.keys()} + with suppress(Exception): + field.resolver(**iargs) - if not perm: # if no expected permission is defined, we expect the check to not be called - locals()[f'mock_check_{perm_type}'].assert_not_called() # nosemgrep - pytest.skip(msg + f' Reason: {reason.value}') - elif perm_type == 'resource': - mock_check_resource.assert_any_call( - session=ANY, - resource_uri=ANY, - username=username, - groups=groups, - permission_name=perm, - ) - elif perm_type == 'tenant': - mock_check_tenant.assert_any_call( - session=ANY, - username=username, - groups=groups, - tenant_name=ANY, - permission_name=perm, - ) - else: - raise ValueError(f'unknown permission type {perm_type}') + if not perm: # if no expected permission is defined, we expect the check to not be called + locals()[f'mock_check_{perm_type}'].assert_not_called() # nosemgrep + pytest.skip(msg + f' Reason: {reason.value}') + elif perm_type == 'resource': + mock_check_resource.assert_any_call( + session=ANY, + resource_uri=ANY, + username=username, + groups=groups, + permission_name=perm, + ) + elif perm_type == 'tenant': + mock_check_tenant.assert_any_call( + session=ANY, + username=username, + groups=groups, + tenant_name=ANY, + permission_name=perm, + ) + else: + raise ValueError(f'unknown permission type {perm_type}') From d9fcfa26aa7d2d54996da93c582264ef8df93976 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Tue, 3 Dec 2024 17:09:00 +0200 Subject: [PATCH 46/47] add tenant_admin checks --- tests/test_permissions.py | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/tests/test_permissions.py b/tests/test_permissions.py index fff788afc..92d2d080d 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -138,7 +138,6 @@ class IgnoreReason(Enum): SIMPLIFIED = 'returns a simplified response' USERLIMITED = 'returns user resources in application' CUSTOM = 'custom permissions checks' - ADMINLIMITED = 'limited to resource owners/admin' NOTREQUIRED = 'permission check is not required' @@ -152,14 +151,16 @@ class TestData: resource_perm: str = None tenant_ignore: IgnoreReason = None tenant_perm: str = None + tenant_admin_ignore: IgnoreReason = IgnoreReason.NOTREQUIRED + tenant_admin_perm: bool = False - def get_perm(self, _type: str) -> IgnoreReason: + def get_perm(self, _type: str) -> str: return getattr(self, f'{_type}_perm') - def get_ignore(self, _type) -> str: + def get_ignore(self, _type) -> IgnoreReason: return getattr(self, f'{_type}_ignore') - def get(self, _type) -> Tuple[IgnoreReason, str]: + def get(self, _type) -> Tuple[str, IgnoreReason]: return self.get_perm(_type), self.get_ignore(_type) def __post_init__(self): @@ -183,7 +184,7 @@ def __post_init__(self): resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('AttachedMetadataFormField', 'hasTenantPermissions'): TestData( - resource_ignore=IgnoreReason.USERROLEINRESOURCE, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.USERROLEINRESOURCE, tenant_ignore=IgnoreReason.TENANT, tenant_admin_perm=True ), field_id('Category', 'associations'): TestData( resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -341,7 +342,7 @@ def __post_init__(self): resource_perm=LIST_ENVIRONMENT_GROUP_PERMISSIONS, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Group', 'tenantPermissions'): TestData( - resource_ignore=IgnoreReason.USERROLEINRESOURCE, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.USERROLEINRESOURCE, tenant_ignore=IgnoreReason.TENANT, tenant_admin_perm=True ), field_id('MetadataForm', 'fields'): TestData( resource_ignore=IgnoreReason.INTRAMODULE, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -356,7 +357,7 @@ def __post_init__(self): resource_ignore=IgnoreReason.PUBLIC, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('MetadataFormSearchResult', 'hasTenantPermissions'): TestData( - resource_ignore=IgnoreReason.USERROLEINRESOURCE, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.USERROLEINRESOURCE, tenant_ignore=IgnoreReason.TENANT, tenant_admin_perm=True ), field_id('Mutation', 'DisableDataSubscriptions'): TestData( tenant_perm=MANAGE_ENVIRONMENTS, resource_perm=ENABLE_ENVIRONMENT_SUBSCRIPTIONS @@ -573,11 +574,11 @@ def __post_init__(self): tenant_ignore=IgnoreReason.TENANT, resource_ignore=IgnoreReason.NOTREQUIRED ), field_id('Mutation', 'startReindexCatalog'): TestData( - tenant_ignore=IgnoreReason.TENANT, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_ignore=IgnoreReason.TENANT, resource_ignore=IgnoreReason.TENANT, tenant_admin_perm=True ), field_id('Mutation', 'startSagemakerNotebook'): TestData(tenant_perm=MANAGE_NOTEBOOKS, resource_perm=GET_NOTEBOOK), field_id('Mutation', 'stopMaintenanceWindow'): TestData( - tenant_ignore=IgnoreReason.TENANT, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_ignore=IgnoreReason.TENANT, resource_ignore=IgnoreReason.TENANT, tenant_admin_perm=True ), field_id('Mutation', 'stopSagemakerNotebook'): TestData(tenant_perm=MANAGE_NOTEBOOKS, resource_perm=GET_NOTEBOOK), field_id('Mutation', 'submitShareExtension'): TestData( @@ -640,7 +641,7 @@ def __post_init__(self): tenant_perm=MANAGE_REDSHIFT_DATASETS, resource_perm=UPDATE_REDSHIFT_DATASET_TABLE ), field_id('Mutation', 'updateSSMParameter'): TestData( - tenant_ignore=IgnoreReason.TENANT, resource_ignore=IgnoreReason.NOTREQUIRED + tenant_ignore=IgnoreReason.TENANT, resource_ignore=IgnoreReason.TENANT, tenant_admin_perm=True ), field_id('Mutation', 'updateShareExpirationPeriod'): TestData( tenant_perm=MANAGE_SHARES, resource_perm=SUBMIT_SHARE_OBJECT @@ -857,7 +858,7 @@ def __post_init__(self): resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.USERLIMITED ), field_id('Query', 'listAttachedMetadataForms'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.TENANT, tenant_admin_perm=True ), field_id('Query', 'listConnectionGroupNoPermissions'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -887,7 +888,7 @@ def __post_init__(self): resource_perm=LIST_ENVIRONMENT_DATASETS, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listEntityMetadataForms'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.TENANT, tenant_admin_perm=True ), field_id('Query', 'listEnvironmentConsumptionRoles'): TestData( resource_perm=LIST_ENVIRONMENT_CONSUMPTION_ROLES, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -980,13 +981,13 @@ def __post_init__(self): resource_perm=GET_SHARE_OBJECT, tenant_ignore=IgnoreReason.NOTREQUIRED ), field_id('Query', 'listTenantGroups'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.TENANT + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.TENANT, tenant_admin_perm=True ), field_id('Query', 'listTenantPermissions'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.TENANT + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.TENANT, tenant_admin_perm=True ), field_id('Query', 'listUserMetadataForms'): TestData( - resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED + resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.TENANT, tenant_admin_perm=True ), field_id('Query', 'listUsersForGroup'): TestData( resource_ignore=IgnoreReason.NOTREQUIRED, tenant_ignore=IgnoreReason.NOTREQUIRED @@ -1184,14 +1185,16 @@ def test_all_resolvers_have_test_data(): @pytest.mark.parametrize('field', ALL_PARAMS) -@pytest.mark.parametrize('perm_type', ['resource', 'tenant']) +@pytest.mark.parametrize('perm_type', ['resource', 'tenant', 'tenant_admin']) @patch('dataall.base.context._request_storage') @patch('dataall.core.permissions.services.resource_policy_service.ResourcePolicyService.check_user_resource_permission') @patch('dataall.core.permissions.services.group_policy_service.GroupPolicyService.check_group_environment_permission') @patch('dataall.core.permissions.services.tenant_policy_service.TenantPolicyService.check_user_tenant_permission') +@patch('dataall.core.permissions.services.tenant_policy_service.TenantPolicyValidationService.is_tenant_admin') @patch('dataall.core.stacks.db.target_type_repositories.TargetType.get_resource_read_permission_name') def test_permissions( mock_perm_name, + mock_check_tenant_admin, mock_check_tenant, mock_check_group, mock_check_resource, @@ -1236,5 +1239,7 @@ def test_permissions( tenant_name=ANY, permission_name=perm, ) + elif perm_type == 'tenant_admin': + mock_check_tenant_admin.assert_called() else: raise ValueError(f'unknown permission type {perm_type}') From e65674ca13d964c810a1836b8beb5e6171bfe586 Mon Sep 17 00:00:00 2001 From: Petros Kalos Date: Tue, 3 Dec 2024 17:14:28 +0200 Subject: [PATCH 47/47] remove inf loop workaround --- tests/test_permissions.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/test_permissions.py b/tests/test_permissions.py index 92d2d080d..80c664389 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -1162,10 +1162,6 @@ def mock_input_validation(mocker): return_value='MANAGE_ENVIRONMENTS', ) mocker.patch('dataall.modules.shares_base.api.resolvers.RequestValidator', MagicMock()) - # workaround infinite loop when checking GlossaryResourceAccess.is_owner() - mocker.patch( - 'dataall.modules.catalog.db.glossary_repositories.GlossaryRepository.get_node' - ).side_effect = RuntimeError # mock aws calls for speed mocker.patch('dataall.base.aws.sts.SessionHelper._get_parameter_value') mocker.patch('dataall.base.aws.sts.SessionHelper.remote_session')