package com.thinkbiganalytics.integration.access; /*- * #%L * kylo-service-app * %% * Copyright (C) 2017 ThinkBig Analytics * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import com.jayway.restassured.response.Response; import com.thinkbiganalytics.feedmgr.rest.model.FeedCategory; import com.thinkbiganalytics.feedmgr.rest.model.FeedMetadata; import com.thinkbiganalytics.feedmgr.rest.model.FeedSummary; import com.thinkbiganalytics.feedmgr.rest.model.NifiFeed; import com.thinkbiganalytics.feedmgr.rest.model.RegisteredTemplate; import com.thinkbiganalytics.feedmgr.security.FeedServicesAccessControl; import com.thinkbiganalytics.feedmgr.service.template.ExportImportTemplateService; import com.thinkbiganalytics.integration.IntegrationTestBase; import com.thinkbiganalytics.rest.model.RestResponseStatus; import com.thinkbiganalytics.security.rest.model.Action; import com.thinkbiganalytics.security.rest.model.ActionGroup; import com.thinkbiganalytics.security.rest.model.PermissionsChange; import com.thinkbiganalytics.security.rest.model.RoleMembershipChange; import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static com.thinkbiganalytics.integration.UserContext.User.ADMIN; import static com.thinkbiganalytics.integration.UserContext.User.ANALYST; import static java.net.HttpURLConnection.HTTP_FORBIDDEN; import static java.net.HttpURLConnection.HTTP_NOT_FOUND; /** * Asserts that Category, Template and Feeds are only accessible when given permission to do so. */ public class EntityLevelAccessIT extends IntegrationTestBase { private static final Logger LOG = LoggerFactory.getLogger(EntityLevelAccessIT.class); private static final String GROUP_ANALYSTS = "analysts"; private static final String SERVICES = "services"; private static final String PERMISSION_READ_ONLY = "readOnly"; private static final String PERMISSION_EDITOR = "editor"; private static final String PERMISSION_ADMIN = "admin"; private static final String PERMISSION_FEED_CREATOR = "feedCreator"; private static final String FEED_EDIT_FORBIDDEN = "Error saving Feed Not authorized to perform the action: Edit Feeds"; private static final String FEED_NOT_FOUND = "Error saving Feed Feed not found for id"; private FeedCategory category; private ExportImportTemplateService.ImportTemplate ingestTemplate; private FeedMetadata feed; @Test public void test() { createCategoryWithAdmin(); assertAnalystCantAccessCategories(); // assertCategoryNotEditableForAnalyst(); grantAccessCategoriesToAnalysts(); assertAnalystCanAccessCategoriesButCantSeeCategory(); // grantCategoryEntityPermissionsToAnalysts(); // assertCategoryIsVisibleToAnalyst(); createTemplateWithAdmin(); assertAnalystCantAccessTemplates(); grantAccessTemplatesToAnalysts(); assertAnalystCanAccessTemplatesButCantSeeTemplate(); // grantTemplateEntityPermissionsToAnalysts(); // assertTemplateIsVisibleToAnalyst(); createFeedWithAdmin(); assertAnalystCantAccessFeeds(); assertAnalystCantEditFeed(FEED_EDIT_FORBIDDEN); assertAnalystCantExportFeed(HTTP_FORBIDDEN); assertAnalystCantDisableEnableFeed(HTTP_FORBIDDEN); assertAnalystCantEditFeedPermissions(HTTP_FORBIDDEN); assertAnalystCantDeleteFeed(HTTP_FORBIDDEN); // assertAnalystCantAccessFeedOperations(HTTP_FORBIDDEN); //todo here and everywhere below grantAccessFeedsToAnalysts(); assertAnalystCanAccessFeedsButCantSeeFeed(); assertAnalystCantEditFeed(FEED_EDIT_FORBIDDEN); assertAnalystCantExportFeed(HTTP_FORBIDDEN); assertAnalystCantDisableEnableFeed(HTTP_FORBIDDEN); assertAnalystCantEditFeedPermissions(HTTP_FORBIDDEN); assertAnalystCantDeleteFeed(HTTP_FORBIDDEN); grantFeedEntityPermissionToAnalysts(PERMISSION_READ_ONLY); assertAnalystCanSeeFeed(); assertAnalystCantEditFeed(FEED_EDIT_FORBIDDEN); assertAnalystCantExportFeed(HTTP_FORBIDDEN); assertAnalystCantDisableEnableFeed(HTTP_FORBIDDEN); assertAnalystCantEditFeedPermissions(HTTP_FORBIDDEN); assertAnalystCantDeleteFeed(HTTP_FORBIDDEN); grantFeedEntityPermissionToAnalysts(PERMISSION_EDITOR); assertAnalystCanSeeFeed(); assertAnalystCantEditFeed(FEED_EDIT_FORBIDDEN); //cant edit feed until required service permissions are added for feed, category, template and entity access to category grantEditFeedsToAnalysts(); grantCategoryEntityPermissionToAnalysts(PERMISSION_FEED_CREATOR); assertAnalystCanEditFeed(); assertAnalystCanDisableEnableFeed(); assertAnalystCantExportFeed(HTTP_FORBIDDEN); grantTemplateAndFeedExportToAnalysts(); assertAnalystCanExportFeed(); assertAnalystCantEditFeedPermissions(HTTP_FORBIDDEN); assertAnalystCantDeleteFeed(HTTP_FORBIDDEN); grantFeedEntityPermissionToAnalysts(PERMISSION_ADMIN); assertAnalystCanSeeFeed(); assertAnalystCanEditFeed(); assertAnalystCanExportFeed(); assertAnalystCanDisableEnableFeed(); grantAdminFeedsToAnalysts(); assertAnalystCanEditFeedPermissions(); revokeFeedEntityPermissionsFromAnalysts(); assertAnalystCanAccessFeedsButCantSeeFeed(); assertAnalystCantEditFeed(FEED_NOT_FOUND); assertAnalystCantExportFeed(HTTP_NOT_FOUND); assertAnalystCantDisableEnableFeed(HTTP_NOT_FOUND); assertAnalystCantEditFeedPermissions(HTTP_NOT_FOUND); assertAnalystCantDeleteFeed(HTTP_NOT_FOUND); grantFeedEntityPermissionToAnalysts(PERMISSION_ADMIN); grantCategoryEntityPermissionToAnalysts(PERMISSION_EDITOR); //to delete a feed one has to have an Editor permission to the category too grantAdminFeedsToAnalysts(); assertAnalystCanDeleteFeed(); resetServicePermissionsForAnalysts(); assertAnalystCantAccessCategories(); assertAnalystCantAccessTemplates(); assertAnalystCantAccessFeeds(); } @Override public void teardown() { LOG.debug("EntityLevelAccessIT.teardown"); super.teardown(); } @Override protected void cleanup() { runAs(ADMIN); super.cleanup(); resetServicePermissionsForAnalysts(); } // @Test public void temp() { // category = new FeedCategory(); // category.setId("67d5fd01-096d-41bf-a0b0-e0a0fe8d4587"); // category.setSystemName("entity_access_tests"); // // ingestTemplate = new ExportImportTemplateService.ImportTemplate(); // ingestTemplate.setTemplateId("57ca6102-39bc-42d7-9eff-754663fc4f4b"); // ingestTemplate.setTemplateName("Data Ingest"); // // feed = new FeedMetadata(); // feed.setId("c39209c8-cc50-421e-a5de-25e93cf22c5d"); // feed.setFeedId("c39209c8-cc50-421e-a5de-25e93cf22c5d"); // feed.setFeedName("Feed A"); } private void assertAnalystCantDeleteFeed(int failureStatusCode) { LOG.debug("EntityLevelAccessIT.assertAnalystCantDeleteFeed"); runAs(ANALYST); deleteFeedExpecting(feed.getFeedId(), failureStatusCode); } private void assertAnalystCanDeleteFeed() { LOG.debug("EntityLevelAccessIT.assertAnalystCanDeleteFeed"); runAs(ANALYST); disableFeed(feed.getFeedId()); deleteFeed(feed.getFeedId()); FeedSummary[] feeds = getFeeds(); Assert.assertEquals(0, feeds.length); } private void assertAnalystCantEditFeedPermissions(int status) { LOG.debug("EntityLevelAccessIT.assertAnalystCantEditFeedPermissions"); runAs(ANALYST); RoleMembershipChange roleChange = new RoleMembershipChange(RoleMembershipChange.ChangeType.REPLACE, PERMISSION_ADMIN); roleChange.addGroup(GROUP_ANALYSTS); setFeedEntityPermissionsExpectingStatus(roleChange, feed.getFeedId(), status); } private void assertAnalystCanEditFeedPermissions() { LOG.debug("EntityLevelAccessIT.assertAnalystCanEditFeedPermissions"); runAs(ANALYST); RoleMembershipChange roleChange = new RoleMembershipChange(RoleMembershipChange.ChangeType.REPLACE, PERMISSION_ADMIN); roleChange.addGroup(GROUP_ANALYSTS); setFeedEntityPermissions(roleChange, feed.getFeedId()); } private void assertAnalystCantDisableEnableFeed(int code) { LOG.debug("EntityLevelAccessIT.assertAnalystCantDisableEnableFeed"); runAs(ANALYST); disableFeedExpecting(feed.getFeedId(), code); enableFeedExpecting(feed.getFeedId(), code); } private void assertAnalystCanDisableEnableFeed() { LOG.debug("EntityLevelAccessIT.assertAnalystCanDisableEnableFeed"); runAs(ANALYST); disableFeed(feed.getFeedId()); enableFeed(feed.getFeedId()); } private void assertAnalystCantExportFeed(int failureStatusCode) { LOG.debug("EntityLevelAccessIT.assertAnalystCantExportFeed"); runAs(ANALYST); exportFeedExpecting(feed.getFeedId(), failureStatusCode); } private void assertAnalystCanExportFeed() { LOG.debug("EntityLevelAccessIT.assertAnalystCanExportFeed"); runAs(ANALYST); exportFeed(feed.getFeedId()); } private void assertAnalystCantEditFeed(String errorMessage) { LOG.debug("EntityLevelAccessIT.assertAnalystCantEditFeed"); runAs(ANALYST); FeedMetadata editFeedRequest = getEditFeedRequest(); NifiFeed feed = createFeed(editFeedRequest); Assert.assertEquals(1, feed.getErrorMessages().size()); Assert.assertTrue(feed.getErrorMessages().get(0).startsWith(errorMessage)); } private void assertAnalystCanEditFeed() { LOG.debug("EntityLevelAccessIT.assertAnalystCanEditFeed"); runAs(ANALYST); FeedMetadata editFeedRequest = getEditFeedRequest(); NifiFeed feed = createFeed(editFeedRequest); Assert.assertTrue(feed.getErrorMessages() == null); } private FeedMetadata getEditFeedRequest() { FeedMetadata editFeedRequest = getCreateFeedRequest(category, ingestTemplate, feed.getFeedName()); editFeedRequest.setId(feed.getId()); editFeedRequest.setFeedId(feed.getFeedId()); editFeedRequest.setDescription("New Description"); editFeedRequest.setIsNew(false); return editFeedRequest; } private void assertAnalystCanAccessFeedsButCantSeeFeed() { LOG.debug("EntityLevelAccessIT.assertAnalystCanAccessFeedsButCantSeeFeed"); runAs(ANALYST); FeedSummary[] feeds = getFeeds(); Assert.assertEquals(0, feeds.length); } private void assertAnalystCanSeeFeed() { LOG.debug("EntityLevelAccessIT.assertAnalystCanSeeFeed"); runAs(ANALYST); FeedSummary[] feeds = getFeeds(); Assert.assertEquals(1, feeds.length); } private void createFeedWithAdmin() { LOG.debug("EntityLevelAccessIT.createFeedWithAdmin"); runAs(ADMIN); FeedMetadata feedRequest = getCreateFeedRequest(category, ingestTemplate, "Feed A"); feed = createFeed(feedRequest).getFeedMetadata(); } private void assertAnalystCanAccessTemplatesButCantSeeTemplate() { LOG.debug("EntityLevelAccessIT.assertAnalystCanAccessTemplatesButCantSeeTemplate"); runAs(ANALYST); RegisteredTemplate[] templates = getTemplates(); Assert.assertEquals(0, templates.length); } private void createTemplateWithAdmin() { LOG.debug("EntityLevelAccessIT.createTemplateWithAdmin"); runAs(ADMIN); ingestTemplate = importDataIngestTemplate(); } private void assertAnalystCanAccessCategoriesButCantSeeCategory() { LOG.debug("EntityLevelAccessIT.assertAnalystCanAccessCategoriesButCantSeeCategory"); runAs(ANALYST); FeedCategory[] categories = getCategories(); Assert.assertEquals(0, categories.length); } private void grantEditFeedsToAnalysts() { LOG.debug("EntityLevelAccessIT.grantEditFeedsToAnalysts"); runAs(ADMIN); Action feedsSupport = createAction(FeedServicesAccessControl.FEEDS_SUPPORT); Action accessFeeds = createAction(FeedServicesAccessControl.ACCESS_FEEDS); accessFeeds.addAction(createAction(FeedServicesAccessControl.EDIT_FEEDS)); feedsSupport.addAction(accessFeeds); grantServiceActionToAnalysts(feedsSupport); } private void grantTemplateAndFeedExportToAnalysts() { LOG.debug("EntityLevelAccessIT.grantTemplateAndFeedExportToAnalysts"); runAs(ADMIN); Action feedsSupport = createAction(FeedServicesAccessControl.FEEDS_SUPPORT); Action accessFeeds = createAction(FeedServicesAccessControl.ACCESS_FEEDS); accessFeeds.addAction(createAction(FeedServicesAccessControl.EXPORT_FEEDS)); Action accessTemplates = createAction(FeedServicesAccessControl.ACCESS_TEMPLATES); accessTemplates.addAction(createAction(FeedServicesAccessControl.EXPORT_TEMPLATES)); feedsSupport.addAction(accessTemplates); feedsSupport.addAction(accessFeeds); grantServiceActionToAnalysts(feedsSupport); } private void grantAdminFeedsToAnalysts() { LOG.debug("EntityLevelAccessIT.grantAdminFeedsToAnalysts"); runAs(ADMIN); Action feedsSupport = createAction(FeedServicesAccessControl.FEEDS_SUPPORT); Action accessFeeds = createAction(FeedServicesAccessControl.ACCESS_FEEDS); accessFeeds.addAction(createAction(FeedServicesAccessControl.ADMIN_FEEDS)); feedsSupport.addAction(accessFeeds); grantServiceActionToAnalysts(feedsSupport); } private void grantAccessTemplatesToAnalysts() { LOG.debug("EntityLevelAccessIT.grantAccessTemplatesToAnalysts"); runAs(ADMIN); Action feedsSupport = createAction(FeedServicesAccessControl.FEEDS_SUPPORT); feedsSupport.addAction(createAction(FeedServicesAccessControl.ACCESS_TEMPLATES)); grantServiceActionToAnalysts(feedsSupport); } private void grantAccessCategoriesToAnalysts() { LOG.debug("EntityLevelAccessIT.grantAccessCategoriesToAnalysts"); runAs(ADMIN); Action feedsSupport = createAction(FeedServicesAccessControl.FEEDS_SUPPORT); feedsSupport.addAction(createAction(FeedServicesAccessControl.ACCESS_CATEGORIES)); grantServiceActionToAnalysts(feedsSupport); } private void grantAccessFeedsToAnalysts() { LOG.debug("EntityLevelAccessIT.grantAccessFeedsToAnalysts"); Action feedsSupport = createAction(FeedServicesAccessControl.FEEDS_SUPPORT); feedsSupport.addAction(createAction(FeedServicesAccessControl.ACCESS_FEEDS)); grantServiceActionToAnalysts(feedsSupport); } private void createCategoryWithAdmin() { LOG.debug("EntityLevelAccessIT.createCategoryWithAdmin"); runAs(ADMIN); category = createCategory("Entity Access Tests"); } private void assertAnalystCantAccessCategories() { LOG.debug("EntityLevelAccessIT.assertAnalystCantAccessCategories"); runAs(ANALYST); Response response = getCategoriesExpectingStatus(HTTP_FORBIDDEN); RestResponseStatus status = response.as(RestResponseStatus.class); Assert.assertEquals("Not authorized to perform the action: Access Categories", status.getMessage()); } private void assertAnalystCantAccessTemplates() { LOG.debug("EntityLevelAccessIT.assertAnalystCantAccessTemplates"); runAs(ANALYST); Response response = getTemplatesExpectingStatus(HTTP_FORBIDDEN); RestResponseStatus status = response.as(RestResponseStatus.class); Assert.assertEquals("Not authorized to perform the action: Access Templates", status.getMessage()); } private void assertAnalystCantAccessFeeds() { LOG.debug("EntityLevelAccessIT.assertAnalystCantAccessFeeds"); runAs(ANALYST); Response response = getFeedsExpectingStatus(HTTP_FORBIDDEN); RestResponseStatus status = response.as(RestResponseStatus.class); Assert.assertEquals("Not authorized to perform the action: Access Feeds", status.getMessage()); } private void grantServiceActionToAnalysts(Action action) { LOG.debug("EntityLevelAccessIT.grantServiceActionToAnalysts"); runAs(ADMIN); ActionGroup actions = new ActionGroup(SERVICES); actions.addAction(action); PermissionsChange permissionsChange = new PermissionsChange(PermissionsChange.ChangeType.REPLACE, actions); permissionsChange.addGroup(GROUP_ANALYSTS); permissionsChange.union(getServicePermissions(GROUP_ANALYSTS)); setServicePermissions(permissionsChange); } private void resetServicePermissionsForAnalysts() { LOG.debug("EntityLevelAccessIT.resetServicePermissionsForAnalysts"); runAs(ADMIN); ActionGroup actions = new ActionGroup(SERVICES); PermissionsChange permissionsChange = new PermissionsChange(PermissionsChange.ChangeType.REPLACE, actions); permissionsChange.addGroup(GROUP_ANALYSTS); setServicePermissions(permissionsChange); } private void grantFeedEntityPermissionToAnalysts(String roleName) { LOG.debug("EntityLevelAccessIT.grantFeedEntityPermissionToAnalysts " + roleName); runAs(ADMIN); RoleMembershipChange roleChange = new RoleMembershipChange(RoleMembershipChange.ChangeType.REPLACE, roleName); roleChange.addGroup(GROUP_ANALYSTS); setFeedEntityPermissions(roleChange, feed.getFeedId()); } private void grantCategoryEntityPermissionToAnalysts(String roleName) { LOG.debug("EntityLevelAccessIT.grantCategoryEntityPermissionToAnalysts " + roleName); runAs(ADMIN); RoleMembershipChange roleChange = new RoleMembershipChange(RoleMembershipChange.ChangeType.REPLACE, roleName); roleChange.addGroup(GROUP_ANALYSTS); setCategoryEntityPermissions(roleChange, category.getId()); } private void revokeFeedEntityPermissionsFromAnalysts() { LOG.debug("EntityLevelAccessIT.revokeFeedEntityPermissionsFromAnalysts"); runAs(ADMIN); RoleMembershipChange roleChange = new RoleMembershipChange(RoleMembershipChange.ChangeType.REPLACE, PERMISSION_READ_ONLY); setFeedEntityPermissions(roleChange, feed.getFeedId()); roleChange = new RoleMembershipChange(RoleMembershipChange.ChangeType.REPLACE, PERMISSION_EDITOR); setFeedEntityPermissions(roleChange, feed.getFeedId()); roleChange = new RoleMembershipChange(RoleMembershipChange.ChangeType.REPLACE, PERMISSION_ADMIN); setFeedEntityPermissions(roleChange, feed.getFeedId()); } private static Action createAction(com.thinkbiganalytics.security.action.Action feedsSupport) { return new Action(feedsSupport.getSystemName(), feedsSupport.getTitle(), feedsSupport.getDescription()); } }