from mock import patch import pytest from flask_principal import AnonymousIdentity from endpoints.api import api from endpoints.api.repositorynotification import RepositoryNotification from endpoints.api.permission import RepositoryUserTransitivePermission from endpoints.api.team import OrganizationTeamSyncing from endpoints.api.test.shared import conduct_api_call from endpoints.api.repository import RepositoryTrust from endpoints.api.signing import RepositorySignatures from endpoints.api.search import ConductRepositorySearch from endpoints.api.superuser import SuperUserRepositoryBuildLogs, SuperUserRepositoryBuildResource from endpoints.api.superuser import SuperUserRepositoryBuildStatus from endpoints.test.shared import client_with_identity, toggle_feature from test.fixtures import * TEAM_PARAMS = {'orgname': 'buynlarge', 'teamname': 'owners'} BUILD_PARAMS = {'build_uuid': 'test-1234'} REPO_PARAMS = {'repository': 'devtable/someapp'} SEARCH_PARAMS = {'query': ''} NOTIFICATION_PARAMS = {'namespace': 'devtable', 'repository': 'devtable/simple', 'uuid': 'some uuid'} @pytest.mark.parametrize('resource,method,params,body,identity,expected', [ (OrganizationTeamSyncing, 'POST', TEAM_PARAMS, {}, None, 403), (OrganizationTeamSyncing, 'POST', TEAM_PARAMS, {}, 'freshuser', 403), (OrganizationTeamSyncing, 'POST', TEAM_PARAMS, {}, 'reader', 403), (OrganizationTeamSyncing, 'POST', TEAM_PARAMS, {}, 'devtable', 400), (OrganizationTeamSyncing, 'DELETE', TEAM_PARAMS, {}, None, 403), (OrganizationTeamSyncing, 'DELETE', TEAM_PARAMS, {}, 'freshuser', 403), (OrganizationTeamSyncing, 'DELETE', TEAM_PARAMS, {}, 'reader', 403), (OrganizationTeamSyncing, 'DELETE', TEAM_PARAMS, {}, 'devtable', 200), (ConductRepositorySearch, 'GET', SEARCH_PARAMS, None, None, 200), (ConductRepositorySearch, 'GET', SEARCH_PARAMS, None, 'freshuser', 200), (ConductRepositorySearch, 'GET', SEARCH_PARAMS, None, 'reader', 200), (ConductRepositorySearch, 'GET', SEARCH_PARAMS, None, 'devtable', 200), (SuperUserRepositoryBuildLogs, 'GET', BUILD_PARAMS, None, None, 401), (SuperUserRepositoryBuildLogs, 'GET', BUILD_PARAMS, None, 'freshuser', 403), (SuperUserRepositoryBuildLogs, 'GET', BUILD_PARAMS, None, 'reader', 403), (SuperUserRepositoryBuildLogs, 'GET', BUILD_PARAMS, None, 'devtable', 400), (SuperUserRepositoryBuildStatus, 'GET', BUILD_PARAMS, None, None, 401), (SuperUserRepositoryBuildStatus, 'GET', BUILD_PARAMS, None, 'freshuser', 403), (SuperUserRepositoryBuildStatus, 'GET', BUILD_PARAMS, None, 'reader', 403), (SuperUserRepositoryBuildStatus, 'GET', BUILD_PARAMS, None, 'devtable', 400), (SuperUserRepositoryBuildResource, 'GET', BUILD_PARAMS, None, None, 401), (SuperUserRepositoryBuildResource, 'GET', BUILD_PARAMS, None, 'freshuser', 403), (SuperUserRepositoryBuildResource, 'GET', BUILD_PARAMS, None, 'reader', 403), (SuperUserRepositoryBuildResource, 'GET', BUILD_PARAMS, None, 'devtable', 404), (RepositorySignatures, 'GET', REPO_PARAMS, {}, 'freshuser', 403), (RepositorySignatures, 'GET', REPO_PARAMS, {}, 'reader', 403), (RepositorySignatures, 'GET', REPO_PARAMS, {}, 'devtable', 404), (RepositoryNotification, 'POST', NOTIFICATION_PARAMS, {}, None, 403), (RepositoryNotification, 'POST', NOTIFICATION_PARAMS, {}, 'freshuser', 403), (RepositoryNotification, 'POST', NOTIFICATION_PARAMS, {}, 'reader', 403), (RepositoryNotification, 'POST', NOTIFICATION_PARAMS, {}, 'devtable', 400), (RepositoryTrust, 'POST', REPO_PARAMS, {'trust_enabled': True}, None, 403), (RepositoryTrust, 'POST', REPO_PARAMS, {'trust_enabled': True}, 'freshuser', 403), (RepositoryTrust, 'POST', REPO_PARAMS, {'trust_enabled': True}, 'reader', 403), (RepositoryTrust, 'POST', REPO_PARAMS, {'trust_enabled': True}, 'devtable', 404), (RepositoryUserTransitivePermission, 'GET', {'username': 'A2O9','repository': 'public/publicrepo'}, None, None, 401), (RepositoryUserTransitivePermission, 'GET', {'username': 'A2O9','repository': 'public/publicrepo'}, None, 'freshuser', 403), (RepositoryUserTransitivePermission, 'GET', {'username': 'A2O9','repository': 'public/publicrepo'}, None, 'reader', 403), (RepositoryUserTransitivePermission, 'GET', {'username': 'A2O9','repository': 'public/publicrepo'}, None, 'devtable', 403), (RepositoryUserTransitivePermission, 'GET', {'username': 'A2O9','repository': 'devtable/shared'}, None, None, 401), (RepositoryUserTransitivePermission, 'GET', {'username': 'A2O9','repository': 'devtable/shared'}, None, 'freshuser', 403), (RepositoryUserTransitivePermission, 'GET', {'username': 'A2O9','repository': 'devtable/shared'}, None, 'reader', 403), (RepositoryUserTransitivePermission, 'GET', {'username': 'A2O9','repository': 'devtable/shared'}, None, 'devtable', 404), (RepositoryUserTransitivePermission, 'GET', {'username': 'A2O9','repository': 'buynlarge/orgrepo'}, None, None, 401), (RepositoryUserTransitivePermission, 'GET', {'username': 'A2O9','repository': 'buynlarge/orgrepo'}, None, 'freshuser', 403), (RepositoryUserTransitivePermission, 'GET', {'username': 'A2O9','repository': 'buynlarge/orgrepo'}, None, 'reader', 403), (RepositoryUserTransitivePermission, 'GET', {'username': 'A2O9','repository': 'buynlarge/orgrepo'}, None, 'devtable', 404), (RepositoryUserTransitivePermission, 'GET', {'username': 'devtable','repository': 'devtable/shared'}, None, 'devtable', 200), (RepositoryUserTransitivePermission, 'GET', {'username': 'devtable','repository': 'devtable/nope'}, None, 'devtable', 404), ]) def test_api_security(resource, method, params, body, identity, expected, client): with client_with_identity(identity, client) as cl: conduct_api_call(cl, resource, method, params, body, expected) @pytest.mark.parametrize('is_superuser', [ (True), (False), ]) @pytest.mark.parametrize('allow_nonsuperuser', [ (True), (False), ]) @pytest.mark.parametrize('method, expected', [ ('POST', 400), ('DELETE', 200), ]) def test_team_sync_security(is_superuser, allow_nonsuperuser, method, expected, client): def is_superuser_method(_): return is_superuser with patch('auth.permissions.superusers.is_superuser', is_superuser_method): with toggle_feature('NONSUPERUSER_TEAM_SYNCING_SETUP', allow_nonsuperuser): with client_with_identity('devtable', client) as cl: expect_success = is_superuser or allow_nonsuperuser expected_status = expected if expect_success else 403 conduct_api_call(cl, OrganizationTeamSyncing, method, TEAM_PARAMS, {}, expected_status)