http://git-wip-us.apache.org/repos/asf/nifi/blob/f0811ca4/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITAccessTokenEndpoint.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITAccessTokenEndpoint.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITAccessTokenEndpoint.java new file mode 100644 index 0000000..55fa1a4 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITAccessTokenEndpoint.java @@ -0,0 +1,274 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.nifi.integration.accesscontrol; + +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import org.apache.commons.io.FileUtils; +import org.apache.nifi.integration.util.NiFiTestServer; +import org.apache.nifi.integration.util.NiFiTestUser; +import org.apache.nifi.integration.util.SourceTestProcessor; +import org.apache.nifi.nar.ExtensionManager; +import org.apache.nifi.nar.NarClassLoaders; +import org.apache.nifi.security.util.SslContextFactory; +import org.apache.nifi.util.NiFiProperties; +import org.apache.nifi.web.api.dto.AccessConfigurationDTO; +import org.apache.nifi.web.api.dto.AccessStatusDTO; +import org.apache.nifi.web.api.dto.ProcessorDTO; +import org.apache.nifi.web.api.dto.RevisionDTO; +import org.apache.nifi.web.api.entity.AccessConfigurationEntity; +import org.apache.nifi.web.api.entity.AccessStatusEntity; +import org.apache.nifi.web.api.entity.ProcessorEntity; +import org.apache.nifi.web.util.WebUtils; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.net.ssl.SSLContext; +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +/** + * Access token endpoint test. + */ +public class ITAccessTokenEndpoint { + + private static final String CLIENT_ID = "token-endpoint-id"; + private static final String CONTEXT_PATH = "/nifi-api"; + private static final String FLOW_XML_PATH = "target/test-classes/access-control/flow-admin.xml"; + + private static NiFiTestServer SERVER; + private static NiFiTestUser TOKEN_USER; + private static String BASE_URL; + + @BeforeClass + public static void setup() throws Exception { + // configure the location of the nifi properties + File nifiPropertiesFile = new File("src/test/resources/access-control/nifi.properties"); + System.setProperty(NiFiProperties.PROPERTIES_FILE_PATH, nifiPropertiesFile.getAbsolutePath()); + + // update the flow.xml property + NiFiProperties props = NiFiProperties.getInstance(); + props.setProperty("nifi.flow.configuration.file", FLOW_XML_PATH); + + // delete the database directory to avoid issues with re-registration in testRequestAccessUsingToken + FileUtils.deleteDirectory(props.getDatabaseRepositoryPath().toFile()); + + // load extensions + NarClassLoaders.load(props); + ExtensionManager.discoverExtensions(); + + // start the server + SERVER = new NiFiTestServer("src/main/webapp", CONTEXT_PATH); + SERVER.startServer(); + SERVER.loadFlow(); + + // get the base url + BASE_URL = SERVER.getBaseUrl() + CONTEXT_PATH; + + // create the user + final Client client = WebUtils.createClient(null, createTrustContext(props)); + TOKEN_USER = new NiFiTestUser(client, null); + } + + private static SSLContext createTrustContext(final NiFiProperties props) throws Exception { + return SslContextFactory.createTrustSslContext(props.getProperty(NiFiProperties.SECURITY_TRUSTSTORE), + props.getProperty(NiFiProperties.SECURITY_TRUSTSTORE_PASSWD).toCharArray(), + props.getProperty(NiFiProperties.SECURITY_TRUSTSTORE_TYPE), "TLS"); + } + + // ----------- + // LOGIN CONIG + // ----------- + /** + * Test getting access configuration. + * + * @throws Exception ex + */ + @Test + public void testGetAccessConfig() throws Exception { + String url = BASE_URL + "/access/config"; + + ClientResponse response = TOKEN_USER.testGet(url); + + // ensure the request is successful + Assert.assertEquals(200, response.getStatus()); + + // extract the process group + AccessConfigurationEntity accessConfigEntity = response.getEntity(AccessConfigurationEntity.class); + + // ensure there is content + Assert.assertNotNull(accessConfigEntity); + + // extract the process group dto + AccessConfigurationDTO accessConfig = accessConfigEntity.getConfig(); + + // verify config + Assert.assertTrue(accessConfig.getSupportsLogin()); + } + + /** + * Obtains a token and creates a processor using it. + * + * @throws Exception ex + */ + @Test + public void testCreateProcessorUsingToken() throws Exception { + String url = BASE_URL + "/access/token"; + + ClientResponse response = TOKEN_USER.testCreateToken(url, "user@nifi", "whateve"); + + // ensure the request is successful + Assert.assertEquals(201, response.getStatus()); + + // get the token + String token = response.getEntity(String.class); + + // attempt to create a processor with it + createProcessor(token); + } + + private ProcessorDTO createProcessor(final String token) throws Exception { + String url = BASE_URL + "/process-groups/root/processors"; + + // authorization header + Map<String, String> headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + token); + + // create the processor + ProcessorDTO processor = new ProcessorDTO(); + processor.setName("Copy"); + processor.setType(SourceTestProcessor.class.getName()); + + // create the revision + final RevisionDTO revision = new RevisionDTO(); + revision.setClientId(CLIENT_ID); + revision.setVersion(0l); + + // create the entity body + ProcessorEntity entity = new ProcessorEntity(); + entity.setRevision(revision); + entity.setComponent(processor); + + // perform the request + ClientResponse response = TOKEN_USER.testPostWithHeaders(url, entity, headers); + + // ensure the request is successful + Assert.assertEquals(201, response.getStatus()); + + // get the entity body + entity = response.getEntity(ProcessorEntity.class); + + // verify creation + processor = entity.getComponent(); + Assert.assertEquals("Copy", processor.getName()); + Assert.assertEquals("org.apache.nifi.integration.util.SourceTestProcessor", processor.getType()); + + return processor; + } + + /** + * Verifies the response when bad credentials are specified. + * + * @throws Exception ex + */ + @Test + public void testInvalidCredentials() throws Exception { + String url = BASE_URL + "/access/token"; + + ClientResponse response = TOKEN_USER.testCreateToken(url, "user@nifi", "not a real password"); + + // ensure the request is successful + Assert.assertEquals(400, response.getStatus()); + } + + /** + * Verifies the response when the user is known. + * + * @throws Exception ex + */ + @Test + public void testUnknownUser() throws Exception { + String url = BASE_URL + "/access/token"; + + ClientResponse response = TOKEN_USER.testCreateToken(url, "not a real user", "not a real password"); + + // ensure the request is successful + Assert.assertEquals(400, response.getStatus()); + } + + /** + * Request access using access token. + * + * @throws Exception ex + */ + @Test + public void testRequestAccessUsingToken() throws Exception { + String accessStatusUrl = BASE_URL + "/access"; + String accessTokenUrl = BASE_URL + "/access/token"; + + ClientResponse response = TOKEN_USER.testGet(accessStatusUrl); + + // ensure the request is successful + Assert.assertEquals(200, response.getStatus()); + + AccessStatusEntity accessStatusEntity = response.getEntity(AccessStatusEntity.class); + AccessStatusDTO accessStatus = accessStatusEntity.getAccessStatus(); + + // verify unknown + Assert.assertEquals("UNKNOWN", accessStatus.getStatus()); + + response = TOKEN_USER.testCreateToken(accessTokenUrl, "unregistered-user@nifi", "password"); + + // ensure the request is successful + Assert.assertEquals(201, response.getStatus()); + + // get the token + String token = response.getEntity(String.class); + + // authorization header + Map<String, String> headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + token); + + // check the status with the token + response = TOKEN_USER.testGetWithHeaders(accessStatusUrl, null, headers); + + // ensure the request is successful + Assert.assertEquals(200, response.getStatus()); + + accessStatusEntity = response.getEntity(AccessStatusEntity.class); + accessStatus = accessStatusEntity.getAccessStatus(); + + // verify unregistered + Assert.assertEquals("ACTIVE", accessStatus.getStatus()); + } + + @AfterClass + public static void cleanup() throws Exception { + // shutdown the server + SERVER.shutdownServer(); + SERVER = null; + + // look for the flow.xml + File flow = new File(FLOW_XML_PATH); + if (flow.exists()) { + flow.delete(); + } + } +}
http://git-wip-us.apache.org/repos/asf/nifi/blob/f0811ca4/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITConnectionAccessControl.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITConnectionAccessControl.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITConnectionAccessControl.java new file mode 100644 index 0000000..1d8e597 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITConnectionAccessControl.java @@ -0,0 +1,427 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.nifi.integration.accesscontrol; + +import com.sun.jersey.api.client.ClientResponse; +import org.apache.nifi.connectable.ConnectableType; +import org.apache.nifi.integration.util.NiFiTestAuthorizer; +import org.apache.nifi.integration.util.NiFiTestUser; +import org.apache.nifi.web.api.dto.ConnectableDTO; +import org.apache.nifi.web.api.dto.ConnectionDTO; +import org.apache.nifi.web.api.dto.RevisionDTO; +import org.apache.nifi.web.api.dto.flow.FlowDTO; +import org.apache.nifi.web.api.entity.ConnectionEntity; +import org.apache.nifi.web.api.entity.ProcessGroupFlowEntity; +import org.apache.nifi.web.api.entity.ProcessorEntity; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import static org.apache.nifi.integration.accesscontrol.AccessControlHelper.NONE_CLIENT_ID; +import static org.apache.nifi.integration.accesscontrol.AccessControlHelper.READ_CLIENT_ID; +import static org.apache.nifi.integration.accesscontrol.AccessControlHelper.READ_WRITE_CLIENT_ID; +import static org.apache.nifi.integration.accesscontrol.AccessControlHelper.WRITE_CLIENT_ID; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Access control test for connections. + */ +public class ITConnectionAccessControl { + + private static final String FLOW_XML_PATH = "target/test-classes/access-control/flow-connections.xml"; + + private static AccessControlHelper helper; + + @BeforeClass + public static void setup() throws Exception { + helper = new AccessControlHelper(FLOW_XML_PATH); + } + + /** + * Ensures the READ user can get a connection. + * + * @throws Exception ex + */ + @Test + public void testReadUserGetConnection() throws Exception { + final ConnectionEntity entity = getRandomConnection(helper.getReadUser()); + assertTrue(entity.getAccessPolicy().getCanRead()); + assertFalse(entity.getAccessPolicy().getCanWrite()); + assertNotNull(entity.getComponent()); + } + + /** + * Ensures the READ WRITE user can get a connection. + * + * @throws Exception ex + */ + @Test + public void testReadWriteUserGetConnection() throws Exception { + final ConnectionEntity entity = getRandomConnection(helper.getReadWriteUser()); + assertTrue(entity.getAccessPolicy().getCanRead()); + assertTrue(entity.getAccessPolicy().getCanWrite()); + assertNotNull(entity.getComponent()); + } + + /** + * Ensures the WRITE user can get a connection. + * + * @throws Exception ex + */ + @Test + public void testWriteUserGetConnection() throws Exception { + final ConnectionEntity entity = getRandomConnection(helper.getWriteUser()); + assertFalse(entity.getAccessPolicy().getCanRead()); + assertTrue(entity.getAccessPolicy().getCanWrite()); + assertNull(entity.getComponent()); + } + + /** + * Ensures the NONE user can get a connection. + * + * @throws Exception ex + */ + @Test + public void testNoneUserGetConnection() throws Exception { + final ConnectionEntity entity = getRandomConnection(helper.getNoneUser()); + assertFalse(entity.getAccessPolicy().getCanRead()); + assertFalse(entity.getAccessPolicy().getCanWrite()); + assertNull(entity.getComponent()); + } + + /** + * Ensures the READ user cannot put a connection. + * + * @throws Exception ex + */ + @Test + public void testReadUserPutConnection() throws Exception { + final ConnectionEntity entity = getRandomConnection(helper.getReadUser()); + assertTrue(entity.getAccessPolicy().getCanRead()); + assertFalse(entity.getAccessPolicy().getCanWrite()); + assertNotNull(entity.getComponent()); + + // attempt update the name + entity.getRevision().setClientId(READ_CLIENT_ID); + entity.getComponent().setName("Updated Name"); + + // perform the request + final ClientResponse response = updateConnection(helper.getReadUser(), entity); + + // ensure forbidden response + assertEquals(403, response.getStatus()); + } + + /** + * Ensures the READ_WRITE user can put a connection. + * + * @throws Exception ex + */ + @Test + public void testReadWriteUserPutConnection() throws Exception { + final ConnectionEntity entity = getRandomConnection(helper.getReadWriteUser()); + assertTrue(entity.getAccessPolicy().getCanRead()); + assertTrue(entity.getAccessPolicy().getCanWrite()); + assertNotNull(entity.getComponent()); + + final String updatedName = "Updated Name"; + + // attempt to update the name + final long version = entity.getRevision().getVersion(); + entity.getRevision().setClientId(AccessControlHelper.READ_WRITE_CLIENT_ID); + entity.getComponent().setName(updatedName); + + // perform the request + final ClientResponse response = updateConnection(helper.getReadWriteUser(), entity); + + // ensure successful response + assertEquals(200, response.getStatus()); + + // get the response + final ConnectionEntity responseEntity = response.getEntity(ConnectionEntity.class); + + // verify + assertEquals(READ_WRITE_CLIENT_ID, responseEntity.getRevision().getClientId()); + assertEquals(version + 1, responseEntity.getRevision().getVersion().longValue()); + assertEquals(updatedName, responseEntity.getComponent().getName()); + } + + /** + * Ensures the READ_WRITE user can put a connection. + * + * @throws Exception ex + */ + @Test + public void testReadWriteUserPutConnectionThroughInheritedPolicy() throws Exception { + final ConnectionEntity entity = createConnection(NiFiTestAuthorizer.NO_POLICY_COMPONENT_NAME); + + final String updatedName = "Updated name"; + + // attempt to update the name + final long version = entity.getRevision().getVersion(); + entity.getRevision().setClientId(READ_WRITE_CLIENT_ID); + entity.getComponent().setName(updatedName); + + // perform the request + final ClientResponse response = updateConnection(helper.getReadWriteUser(), entity); + + // ensure successful response + assertEquals(200, response.getStatus()); + + // get the response + final ConnectionEntity responseEntity = response.getEntity(ConnectionEntity.class); + + // verify + assertEquals(AccessControlHelper.READ_WRITE_CLIENT_ID, responseEntity.getRevision().getClientId()); + assertEquals(version + 1, responseEntity.getRevision().getVersion().longValue()); + assertEquals(updatedName, responseEntity.getComponent().getName()); + } + + /** + * Ensures the WRITE user can put a connection. + * + * @throws Exception ex + */ + @Test + public void testWriteUserPutConnection() throws Exception { + final ConnectionEntity entity = getRandomConnection(helper.getWriteUser()); + assertFalse(entity.getAccessPolicy().getCanRead()); + assertTrue(entity.getAccessPolicy().getCanWrite()); + assertNull(entity.getComponent()); + + final String updatedName = "Updated Name"; + + // attempt to update the name + final ConnectionDTO requestDto = new ConnectionDTO(); + requestDto.setId(entity.getId()); + requestDto.setName(updatedName); + + final long version = entity.getRevision().getVersion(); + final RevisionDTO requestRevision = new RevisionDTO(); + requestRevision.setVersion(version); + requestRevision.setClientId(AccessControlHelper.WRITE_CLIENT_ID); + + final ConnectionEntity requestEntity = new ConnectionEntity(); + requestEntity.setId(entity.getId()); + requestEntity.setRevision(requestRevision); + requestEntity.setComponent(requestDto); + + // perform the request + final ClientResponse response = updateConnection(helper.getWriteUser(), requestEntity); + + // ensure successful response + assertEquals(200, response.getStatus()); + + // get the response + final ConnectionEntity responseEntity = response.getEntity(ConnectionEntity.class); + + // verify + assertEquals(WRITE_CLIENT_ID, responseEntity.getRevision().getClientId()); + assertEquals(version + 1, responseEntity.getRevision().getVersion().longValue()); + } + + /** + * Ensures the NONE user cannot put a connection. + * + * @throws Exception ex + */ + @Test + public void testNoneUserPutConnection() throws Exception { + final ConnectionEntity entity = getRandomConnection(helper.getNoneUser()); + assertFalse(entity.getAccessPolicy().getCanRead()); + assertFalse(entity.getAccessPolicy().getCanWrite()); + assertNull(entity.getComponent()); + + final String updatedName = "Updated Name"; + + // attempt to update the name + final ConnectionDTO requestDto = new ConnectionDTO(); + requestDto.setId(entity.getId()); + requestDto.setName(updatedName); + + final long version = entity.getRevision().getVersion(); + final RevisionDTO requestRevision = new RevisionDTO(); + requestRevision.setVersion(version); + requestRevision.setClientId(AccessControlHelper.NONE_CLIENT_ID); + + final ConnectionEntity requestEntity = new ConnectionEntity(); + requestEntity.setId(entity.getId()); + requestEntity.setRevision(requestRevision); + requestEntity.setComponent(requestDto); + + // perform the request + final ClientResponse response = updateConnection(helper.getNoneUser(), requestEntity); + + // ensure forbidden response + assertEquals(403, response.getStatus()); + } + + /** + * Ensures the READ user cannot delete a connection. + * + * @throws Exception ex + */ + @Test + public void testReadUserDeleteConnection() throws Exception { + verifyDelete(helper.getReadUser(), AccessControlHelper.READ_CLIENT_ID, 403); + } + + /** + * Ensures the READ WRITE user can delete a connection. + * + * @throws Exception ex + */ + @Test + public void testReadWriteUserDeleteConnection() throws Exception { + verifyDelete(helper.getReadWriteUser(), AccessControlHelper.READ_WRITE_CLIENT_ID, 200); + } + + /** + * Ensures the WRITE user can delete a connection. + * + * @throws Exception ex + */ + @Test + public void testWriteUserDeleteConnection() throws Exception { + verifyDelete(helper.getWriteUser(), AccessControlHelper.WRITE_CLIENT_ID, 200); + } + + /** + * Ensures the NONE user can delete a connection. + * + * @throws Exception ex + */ + @Test + public void testNoneUserDeleteConnection() throws Exception { + verifyDelete(helper.getNoneUser(), NONE_CLIENT_ID, 403); + } + + private ConnectionEntity getRandomConnection(final NiFiTestUser user) throws Exception { + final String url = helper.getBaseUrl() + "/flow/process-groups/root"; + + // get the connections + final ClientResponse response = user.testGet(url); + + // ensure the response was successful + assertEquals(200, response.getStatus()); + + // unmarshal + final ProcessGroupFlowEntity flowEntity = response.getEntity(ProcessGroupFlowEntity.class); + final FlowDTO flowDto = flowEntity.getProcessGroupFlow().getFlow(); + final Set<ConnectionEntity> connections = flowDto.getConnections(); + + // ensure the correct number of connection + assertFalse(connections.isEmpty()); + + // use the first connection as the target + Iterator<ConnectionEntity> connectionIter = connections.iterator(); + assertTrue(connectionIter.hasNext()); + return connectionIter.next(); + } + + private ClientResponse updateConnection(final NiFiTestUser user, final ConnectionEntity entity) throws Exception { + final String url = helper.getBaseUrl() + "/connections/" + entity.getId(); + + // perform the request + return user.testPut(url, entity); + } + + private ConnectionEntity createConnection(final String name) throws Exception { + String url = helper.getBaseUrl() + "/process-groups/root/connections"; + + // get two processors + final ProcessorEntity one = ITProcessorAccessControl.createProcessor(helper, "one"); + final ProcessorEntity two = ITProcessorAccessControl.createProcessor(helper, "two"); + + // create the source connectable + ConnectableDTO source = new ConnectableDTO(); + source.setId(one.getId()); + source.setType(ConnectableType.PROCESSOR.name()); + + // create the target connectable + ConnectableDTO target = new ConnectableDTO(); + target.setId(two.getId()); + target.setType(ConnectableType.PROCESSOR.name()); + + // create the relationships + Set<String> relationships = new HashSet<>(); + relationships.add("success"); + + // create the connection + ConnectionDTO connection = new ConnectionDTO(); + connection.setName(name); + connection.setSource(source); + connection.setDestination(target); + connection.setSelectedRelationships(relationships); + + // create the revision + final RevisionDTO revision = new RevisionDTO(); + revision.setClientId(READ_WRITE_CLIENT_ID); + revision.setVersion(0L); + + // create the entity body + ConnectionEntity entity = new ConnectionEntity(); + entity.setRevision(revision); + entity.setComponent(connection); + + // perform the request + ClientResponse response = helper.getReadWriteUser().testPost(url, entity); + + // ensure the request is successful + assertEquals(201, response.getStatus()); + + // get the entity body + entity = response.getEntity(ConnectionEntity.class); + + // verify creation + connection = entity.getComponent(); + assertEquals(name, connection.getName()); + + // get the connection + return entity; + } + + private void verifyDelete(final NiFiTestUser user, final String clientId, final int responseCode) throws Exception { + final ConnectionEntity entity = createConnection("Copy"); + + // create the entity body + final Map<String, String> queryParams = new HashMap<>(); + queryParams.put("version", String.valueOf(entity.getRevision().getVersion())); + queryParams.put("clientId", clientId); + + // perform the request + ClientResponse response = user.testDelete(entity.getComponent().getUri(), queryParams); + + // ensure the request is failed with a forbidden status code + assertEquals(responseCode, response.getStatus()); + } + + @AfterClass + public static void cleanup() throws Exception { + helper.cleanup(); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/f0811ca4/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITCountersAccessControl.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITCountersAccessControl.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITCountersAccessControl.java new file mode 100644 index 0000000..2f017f8 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITCountersAccessControl.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.nifi.integration.accesscontrol; + +import com.sun.jersey.api.client.ClientResponse; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.Collections; + +import static org.junit.Assert.assertEquals; + +/** + * Access control test for funnels. + */ +public class ITCountersAccessControl { + + private static final String FLOW_XML_PATH = "target/test-classes/access-control/flow-counters.xml"; + + private static AccessControlHelper helper; + private static String uri; + + @BeforeClass + public static void setup() throws Exception { + helper = new AccessControlHelper(FLOW_XML_PATH); + uri = helper.getBaseUrl() + "/counters"; + } + + /** + * Test get counters. + * + * @throws Exception exception + */ + @Test + public void testGetCounters() throws Exception { + helper.testGenericGetUri(uri); + } + + /** + * Ensures the READ user can get counters. + * + * @throws Exception ex + */ + @Test + public void testUpdateCounters() throws Exception { + final String counterUri = uri + "/my-counter"; + + ClientResponse response; + + // read + response = helper.getReadUser().testPut(counterUri, Collections.emptyMap()); + assertEquals(403, response.getStatus()); + + // read/write + response = helper.getReadWriteUser().testPut(counterUri, Collections.emptyMap()); + assertEquals(404, response.getStatus()); + + // write + response = helper.getWriteUser().testPut(counterUri, Collections.emptyMap()); + assertEquals(404, response.getStatus()); + + // none + response = helper.getNoneUser().testPut(counterUri, Collections.emptyMap()); + assertEquals(403, response.getStatus()); + } + + @AfterClass + public static void cleanup() throws Exception { + helper.cleanup(); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/f0811ca4/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITFlowAccessControl.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITFlowAccessControl.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITFlowAccessControl.java new file mode 100644 index 0000000..9202c42 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITFlowAccessControl.java @@ -0,0 +1,245 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.nifi.integration.accesscontrol; + +import com.sun.jersey.api.client.ClientResponse; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Access control test for funnels. + */ +public class ITFlowAccessControl { + + private static final String FLOW_XML_PATH = "target/test-classes/access-control/flow-flow.xml"; + + private static AccessControlHelper helper; + + @BeforeClass + public static void setup() throws Exception { + helper = new AccessControlHelper(FLOW_XML_PATH, "flow-test-provider"); + } + + /** + * Test get flow. + * + * @throws Exception exception + */ + @Test + public void testGetFlow() throws Exception { + helper.testGenericGetUri(helper.getBaseUrl() + "/flow/process-groups/root"); + } + + // TODO - test update flow + + /** + * Test generate client. + * + * @throws Exception exception + */ + @Test + public void testGenerateClientId() throws Exception { + helper.testGenericGetUri(helper.getBaseUrl() + "/flow/client-id"); + } + + /** + * Test get identity. + * + * @throws Exception exception + */ + @Test + public void testGetIdentity() throws Exception { + helper.testGenericGetUri(helper.getBaseUrl() + "/flow/identity"); + } + + /** + * Test get controller services. + * + * @throws Exception exception + */ + @Test + public void testGetControllerServices() throws Exception { + helper.testGenericGetUri(helper.getBaseUrl() + "/flow/controller/controller-services"); + helper.testGenericGetUri(helper.getBaseUrl() + "/flow/process-groups/root/controller-services"); + } + + /** + * Test get reporting tasks. + * + * @throws Exception exception + */ + @Test + public void testGetReportingTasks() throws Exception { + helper.testGenericGetUri(helper.getBaseUrl() + "/flow/reporting-tasks"); + } + + /** + * Test search. + * + * @throws Exception exception + */ + @Test + public void testSearch() throws Exception { + helper.testGenericGetUri(helper.getBaseUrl() + "/flow/search-results"); + } + + /** + * Test status. + * + * @throws Exception exception + */ + @Test + public void testStatus() throws Exception { + helper.testGenericGetUri(helper.getBaseUrl() + "/flow/status"); + } + + /** + * Test banners. + * + * @throws Exception exception + */ + @Test + public void testBanners() throws Exception { + helper.testGenericGetUri(helper.getBaseUrl() + "/flow/status"); + } + + /** + * Test bulletin board. + * + * @throws Exception exception + */ + @Test + public void testBulletinBoard() throws Exception { + helper.testGenericGetUri(helper.getBaseUrl() + "/flow/bulletin-board"); + } + + /** + * Test about. + * + * @throws Exception exception + */ + @Test + public void testAbout() throws Exception { + helper.testGenericGetUri(helper.getBaseUrl() + "/flow/about"); + } + + /** + * Test get flow config. + * + * @throws Exception exception + */ + @Test + public void testGetFlowConfig() throws Exception { + helper.testGenericGetUri(helper.getBaseUrl() + "/flow/config"); + } + + /** + * Test get status. + * + * @throws Exception exception + */ + @Test + public void testGetStatus() throws Exception { + testComponentSpecificGetUri(helper.getBaseUrl() + "/flow/processors/my-component/status"); + testComponentSpecificGetUri(helper.getBaseUrl() + "/flow/input-ports/my-component/status"); + testComponentSpecificGetUri(helper.getBaseUrl() + "/flow/output-ports/my-component/status"); + testComponentSpecificGetUri(helper.getBaseUrl() + "/flow/remote-process-groups/my-component/status"); + testComponentSpecificGetUri(helper.getBaseUrl() + "/flow/process-groups/my-component/status"); + testComponentSpecificGetUri(helper.getBaseUrl() + "/flow/connections/my-component/status"); + } + + /** + * Test get status history. + * + * @throws Exception exception + */ + @Test + public void testGetStatusHistory() throws Exception { + testComponentSpecificGetUri(helper.getBaseUrl() + "/flow/processors/my-component/status/history"); + testComponentSpecificGetUri(helper.getBaseUrl() + "/flow/remote-process-groups/my-component/status/history"); + testComponentSpecificGetUri(helper.getBaseUrl() + "/flow/process-groups/my-component/status/history"); + testComponentSpecificGetUri(helper.getBaseUrl() + "/flow/connections/my-component/status/history"); + } + + /** + * Test get action. + * + * @throws Exception exception + */ + @Test + public void testGetAction() throws Exception { + final String uri = helper.getBaseUrl() + "/flow/history/1"; + + ClientResponse response; + + // the action does not exist... all users should return 403 + + // read + response = helper.getReadUser().testGet(uri); + assertEquals(403, response.getStatus()); + + // read/write + response = helper.getReadWriteUser().testGet(uri); + assertEquals(403, response.getStatus()); + + // write + response = helper.getWriteUser().testGet(uri); + assertEquals(403, response.getStatus()); + + // none + response = helper.getNoneUser().testGet(uri); + assertEquals(403, response.getStatus()); + } + + /** + * Test get action. + * + * @throws Exception exception + */ + @Test + public void testGetComponentHistory() throws Exception { + helper.testGenericGetUri(helper.getBaseUrl() + "/flow/history/components/my-component"); + } + + public void testComponentSpecificGetUri(final String uri) throws Exception { + ClientResponse response; + + // read + response = helper.getReadUser().testGet(uri); + assertEquals(404, response.getStatus()); + + // read/write + response = helper.getReadWriteUser().testGet(uri); + assertEquals(404, response.getStatus()); + + // write + response = helper.getWriteUser().testGet(uri); + assertEquals(403, response.getStatus()); + + // none + response = helper.getNoneUser().testGet(uri); + assertEquals(403, response.getStatus()); + } + + @AfterClass + public static void cleanup() throws Exception { + helper.cleanup(); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/f0811ca4/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITFunnelAccessControl.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITFunnelAccessControl.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITFunnelAccessControl.java new file mode 100644 index 0000000..5d835fc --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITFunnelAccessControl.java @@ -0,0 +1,361 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.nifi.integration.accesscontrol; + +import com.sun.jersey.api.client.ClientResponse; +import org.apache.nifi.integration.util.NiFiTestUser; +import org.apache.nifi.web.api.dto.FunnelDTO; +import org.apache.nifi.web.api.dto.PositionDTO; +import org.apache.nifi.web.api.dto.RevisionDTO; +import org.apache.nifi.web.api.dto.flow.FlowDTO; +import org.apache.nifi.web.api.entity.FunnelEntity; +import org.apache.nifi.web.api.entity.ProcessGroupFlowEntity; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import static org.apache.nifi.integration.accesscontrol.AccessControlHelper.NONE_CLIENT_ID; +import static org.apache.nifi.integration.accesscontrol.AccessControlHelper.READ_CLIENT_ID; +import static org.apache.nifi.integration.accesscontrol.AccessControlHelper.READ_WRITE_CLIENT_ID; +import static org.apache.nifi.integration.accesscontrol.AccessControlHelper.WRITE_CLIENT_ID; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Access control test for funnels. + */ +public class ITFunnelAccessControl { + + private static final String FLOW_XML_PATH = "target/test-classes/access-control/flow-funnels.xml"; + + private static AccessControlHelper helper; + + @BeforeClass + public static void setup() throws Exception { + helper = new AccessControlHelper(FLOW_XML_PATH); + } + + /** + * Ensures the READ user can get a funnel. + * + * @throws Exception ex + */ + @Test + public void testReadUserGetFunnel() throws Exception { + final FunnelEntity entity = getRandomFunnel(helper.getReadUser()); + assertTrue(entity.getAccessPolicy().getCanRead()); + assertFalse(entity.getAccessPolicy().getCanWrite()); + assertNotNull(entity.getComponent()); + } + + /** + * Ensures the READ WRITE user can get a funnel. + * + * @throws Exception ex + */ + @Test + public void testReadWriteUserGetFunnel() throws Exception { + final FunnelEntity entity = getRandomFunnel(helper.getReadWriteUser()); + assertTrue(entity.getAccessPolicy().getCanRead()); + assertTrue(entity.getAccessPolicy().getCanWrite()); + assertNotNull(entity.getComponent()); + } + + /** + * Ensures the WRITE user can get a funnel. + * + * @throws Exception ex + */ + @Test + public void testWriteUserGetFunnel() throws Exception { + final FunnelEntity entity = getRandomFunnel(helper.getWriteUser()); + assertFalse(entity.getAccessPolicy().getCanRead()); + assertTrue(entity.getAccessPolicy().getCanWrite()); + assertNull(entity.getComponent()); + } + + /** + * Ensures the NONE user can get a funnel. + * + * @throws Exception ex + */ + @Test + public void testNoneUserGetFunnel() throws Exception { + final FunnelEntity entity = getRandomFunnel(helper.getNoneUser()); + assertFalse(entity.getAccessPolicy().getCanRead()); + assertFalse(entity.getAccessPolicy().getCanWrite()); + assertNull(entity.getComponent()); + } + + /** + * Ensures the READ user cannot put a funnel. + * + * @throws Exception ex + */ + @Test + public void testReadUserPutFunnel() throws Exception { + final FunnelEntity entity = getRandomFunnel(helper.getReadUser()); + assertTrue(entity.getAccessPolicy().getCanRead()); + assertFalse(entity.getAccessPolicy().getCanWrite()); + assertNotNull(entity.getComponent()); + + // attempt update the position + entity.getRevision().setClientId(READ_CLIENT_ID); + entity.getComponent().setPosition(new PositionDTO(0.0, 10.0)); + + // perform the request + final ClientResponse response = updateFunnel(helper.getReadUser(), entity); + + // ensure forbidden response + assertEquals(403, response.getStatus()); + } + + /** + * Ensures the READ_WRITE user can put a funnel. + * + * @throws Exception ex + */ + @Test + public void testReadWriteUserPutFunnel() throws Exception { + final FunnelEntity entity = getRandomFunnel(helper.getReadWriteUser()); + assertTrue(entity.getAccessPolicy().getCanRead()); + assertTrue(entity.getAccessPolicy().getCanWrite()); + assertNotNull(entity.getComponent()); + + final double y = 15.0; + + // attempt to update the position + final long version = entity.getRevision().getVersion(); + entity.getRevision().setClientId(AccessControlHelper.READ_WRITE_CLIENT_ID); + entity.getComponent().setPosition(new PositionDTO(0.0, y)); + + // perform the request + final ClientResponse response = updateFunnel(helper.getReadWriteUser(), entity); + + // ensure successful response + assertEquals(200, response.getStatus()); + + // get the response + final FunnelEntity responseEntity = response.getEntity(FunnelEntity.class); + + // verify + assertEquals(READ_WRITE_CLIENT_ID, responseEntity.getRevision().getClientId()); + assertEquals(version + 1, responseEntity.getRevision().getVersion().longValue()); + assertEquals(y, responseEntity.getComponent().getPosition().getY().doubleValue(), 0); + } + + /** + * Ensures the WRITE user can put a funnel. + * + * @throws Exception ex + */ + @Test + public void testWriteUserPutFunnel() throws Exception { + final FunnelEntity entity = getRandomFunnel(helper.getWriteUser()); + assertFalse(entity.getAccessPolicy().getCanRead()); + assertTrue(entity.getAccessPolicy().getCanWrite()); + assertNull(entity.getComponent()); + + final double y = 15.0; + + // attempt to update the position + final FunnelDTO requestDto = new FunnelDTO(); + requestDto.setId(entity.getId()); + requestDto.setPosition(new PositionDTO(0.0, y)); + + final long version = entity.getRevision().getVersion(); + final RevisionDTO requestRevision = new RevisionDTO(); + requestRevision.setVersion(version); + requestRevision.setClientId(AccessControlHelper.WRITE_CLIENT_ID); + + final FunnelEntity requestEntity = new FunnelEntity(); + requestEntity.setId(entity.getId()); + requestEntity.setRevision(requestRevision); + requestEntity.setComponent(requestDto); + + // perform the request + final ClientResponse response = updateFunnel(helper.getWriteUser(), requestEntity); + + // ensure successful response + assertEquals(200, response.getStatus()); + + // get the response + final FunnelEntity responseEntity = response.getEntity(FunnelEntity.class); + + // verify + assertEquals(WRITE_CLIENT_ID, responseEntity.getRevision().getClientId()); + assertEquals(version + 1, responseEntity.getRevision().getVersion().longValue()); + } + + /** + * Ensures the NONE user cannot put a funnel. + * + * @throws Exception ex + */ + @Test + public void testNoneUserPutFunnel() throws Exception { + final FunnelEntity entity = getRandomFunnel(helper.getNoneUser()); + assertFalse(entity.getAccessPolicy().getCanRead()); + assertFalse(entity.getAccessPolicy().getCanWrite()); + assertNull(entity.getComponent()); + + // attempt to update the position + final FunnelDTO requestDto = new FunnelDTO(); + requestDto.setId(entity.getId()); + requestDto.setPosition(new PositionDTO(0.0, 15.0)); + + final long version = entity.getRevision().getVersion(); + final RevisionDTO requestRevision = new RevisionDTO(); + requestRevision.setVersion(version); + requestRevision.setClientId(AccessControlHelper.NONE_CLIENT_ID); + + final FunnelEntity requestEntity = new FunnelEntity(); + requestEntity.setId(entity.getId()); + requestEntity.setRevision(requestRevision); + requestEntity.setComponent(requestDto); + + // perform the request + final ClientResponse response = updateFunnel(helper.getNoneUser(), requestEntity); + + // ensure forbidden response + assertEquals(403, response.getStatus()); + } + + /** + * Ensures the READ user cannot delete a funnel. + * + * @throws Exception ex + */ + @Test + public void testReadUserDeleteFunnel() throws Exception { + verifyDelete(helper.getReadUser(), AccessControlHelper.READ_CLIENT_ID, 403); + } + + /** + * Ensures the READ WRITE user can delete a funnel. + * + * @throws Exception ex + */ + @Test + public void testReadWriteUserDeleteFunnel() throws Exception { + verifyDelete(helper.getReadWriteUser(), AccessControlHelper.READ_WRITE_CLIENT_ID, 200); + } + + /** + * Ensures the WRITE user can delete a funnel. + * + * @throws Exception ex + */ + @Test + public void testWriteUserDeleteFunnel() throws Exception { + verifyDelete(helper.getWriteUser(), AccessControlHelper.WRITE_CLIENT_ID, 200); + } + + /** + * Ensures the NONE user can delete a funnel. + * + * @throws Exception ex + */ + @Test + public void testNoneUserDeleteFunnel() throws Exception { + verifyDelete(helper.getNoneUser(), NONE_CLIENT_ID, 403); + } + + private FunnelEntity getRandomFunnel(final NiFiTestUser user) throws Exception { + final String url = helper.getBaseUrl() + "/flow/process-groups/root"; + + // get the flow + final ClientResponse response = user.testGet(url); + + // ensure the response was successful + assertEquals(200, response.getStatus()); + + // unmarshal + final ProcessGroupFlowEntity flowEntity = response.getEntity(ProcessGroupFlowEntity.class); + final FlowDTO flowDto = flowEntity.getProcessGroupFlow().getFlow(); + final Set<FunnelEntity> funnels = flowDto.getFunnels(); + + // ensure the correct number of funnels + assertFalse(funnels.isEmpty()); + + // use the first funnel as the target + Iterator<FunnelEntity> funnelIter = funnels.iterator(); + assertTrue(funnelIter.hasNext()); + return funnelIter.next(); + } + + private ClientResponse updateFunnel(final NiFiTestUser user, final FunnelEntity entity) throws Exception { + final String url = helper.getBaseUrl() + "/funnels/" + entity.getId(); + + // perform the request + return user.testPut(url, entity); + } + + private FunnelEntity createFunnel() throws Exception { + String url = helper.getBaseUrl() + "/process-groups/root/funnels"; + + // create the funnel + FunnelDTO funnel = new FunnelDTO(); + + // create the revision + final RevisionDTO revision = new RevisionDTO(); + revision.setClientId(READ_WRITE_CLIENT_ID); + revision.setVersion(0L); + + // create the entity body + FunnelEntity entity = new FunnelEntity(); + entity.setRevision(revision); + entity.setComponent(funnel); + + // perform the request + ClientResponse response = helper.getReadWriteUser().testPost(url, entity); + + // ensure the request is successful + assertEquals(201, response.getStatus()); + + // get the entity body + return response.getEntity(FunnelEntity.class); + } + + private void verifyDelete(final NiFiTestUser user, final String clientId, final int responseCode) throws Exception { + final FunnelEntity entity = createFunnel(); + + // create the entity body + final Map<String, String> queryParams = new HashMap<>(); + queryParams.put("version", String.valueOf(entity.getRevision().getVersion())); + queryParams.put("clientId", clientId); + + // perform the request + ClientResponse response = user.testDelete(entity.getComponent().getUri(), queryParams); + + // ensure the request is failed with a forbidden status code + assertEquals(responseCode, response.getStatus()); + } + + @AfterClass + public static void cleanup() throws Exception { + helper.cleanup(); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/f0811ca4/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITInputPortAccessControl.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITInputPortAccessControl.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITInputPortAccessControl.java new file mode 100644 index 0000000..3dc8f19 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITInputPortAccessControl.java @@ -0,0 +1,405 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.nifi.integration.accesscontrol; + +import com.sun.jersey.api.client.ClientResponse; +import org.apache.nifi.integration.util.NiFiTestAuthorizer; +import org.apache.nifi.integration.util.NiFiTestUser; +import org.apache.nifi.web.api.dto.PortDTO; +import org.apache.nifi.web.api.dto.RevisionDTO; +import org.apache.nifi.web.api.dto.flow.FlowDTO; +import org.apache.nifi.web.api.entity.PortEntity; +import org.apache.nifi.web.api.entity.ProcessGroupFlowEntity; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import static org.apache.nifi.integration.accesscontrol.AccessControlHelper.NONE_CLIENT_ID; +import static org.apache.nifi.integration.accesscontrol.AccessControlHelper.READ_CLIENT_ID; +import static org.apache.nifi.integration.accesscontrol.AccessControlHelper.READ_WRITE_CLIENT_ID; +import static org.apache.nifi.integration.accesscontrol.AccessControlHelper.WRITE_CLIENT_ID; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Access control test for input ports. + */ +public class ITInputPortAccessControl { + + private static final String FLOW_XML_PATH = "target/test-classes/access-control/flow-input-ports.xml"; + + private static AccessControlHelper helper; + private static int count = 0; + + @BeforeClass + public static void setup() throws Exception { + helper = new AccessControlHelper(FLOW_XML_PATH); + } + + /** + * Ensures the READ user can get an input port. + * + * @throws Exception ex + */ + @Test + public void testReadUserGetInputPort() throws Exception { + final PortEntity entity = getRandomInputPort(helper.getReadUser()); + assertTrue(entity.getAccessPolicy().getCanRead()); + assertFalse(entity.getAccessPolicy().getCanWrite()); + assertNotNull(entity.getComponent()); + } + + /** + * Ensures the READ WRITE user can get an input port. + * + * @throws Exception ex + */ + @Test + public void testReadWriteUserGetInputPort() throws Exception { + final PortEntity entity = getRandomInputPort(helper.getReadWriteUser()); + assertTrue(entity.getAccessPolicy().getCanRead()); + assertTrue(entity.getAccessPolicy().getCanWrite()); + assertNotNull(entity.getComponent()); + } + + /** + * Ensures the WRITE user can get an input port. + * + * @throws Exception ex + */ + @Test + public void testWriteUserGetInputPort() throws Exception { + final PortEntity entity = getRandomInputPort(helper.getWriteUser()); + assertFalse(entity.getAccessPolicy().getCanRead()); + assertTrue(entity.getAccessPolicy().getCanWrite()); + assertNull(entity.getComponent()); + } + + /** + * Ensures the NONE user can get an input port. + * + * @throws Exception ex + */ + @Test + public void testNoneUserGetInputPort() throws Exception { + final PortEntity entity = getRandomInputPort(helper.getNoneUser()); + assertFalse(entity.getAccessPolicy().getCanRead()); + assertFalse(entity.getAccessPolicy().getCanWrite()); + assertNull(entity.getComponent()); + } + + /** + * Ensures the READ user cannot put an input port. + * + * @throws Exception ex + */ + @Test + public void testReadUserPutInputPort() throws Exception { + final PortEntity entity = getRandomInputPort(helper.getReadUser()); + assertTrue(entity.getAccessPolicy().getCanRead()); + assertFalse(entity.getAccessPolicy().getCanWrite()); + assertNotNull(entity.getComponent()); + + // attempt update the name + entity.getRevision().setClientId(READ_CLIENT_ID); + entity.getComponent().setName("Updated Name" + count++); + + // perform the request + final ClientResponse response = updateInputPort(helper.getReadUser(), entity); + + // ensure forbidden response + assertEquals(403, response.getStatus()); + } + + /** + * Ensures the READ_WRITE user can put an input port. + * + * @throws Exception ex + */ + @Test + public void testReadWriteUserPutInputPort() throws Exception { + final PortEntity entity = getRandomInputPort(helper.getReadWriteUser()); + assertTrue(entity.getAccessPolicy().getCanRead()); + assertTrue(entity.getAccessPolicy().getCanWrite()); + assertNotNull(entity.getComponent()); + + final String updatedName = "Updated Name" + count++; + + // attempt to update the name + final long version = entity.getRevision().getVersion(); + entity.getRevision().setClientId(AccessControlHelper.READ_WRITE_CLIENT_ID); + entity.getComponent().setName(updatedName); + + // perform the request + final ClientResponse response = updateInputPort(helper.getReadWriteUser(), entity); + + // ensure successful response + assertEquals(200, response.getStatus()); + + // get the response + final PortEntity responseEntity = response.getEntity(PortEntity.class); + + // verify + assertEquals(READ_WRITE_CLIENT_ID, responseEntity.getRevision().getClientId()); + assertEquals(version + 1, responseEntity.getRevision().getVersion().longValue()); + assertEquals(updatedName, responseEntity.getComponent().getName()); + } + + /** + * Ensures the READ_WRITE user can put an input port. + * + * @throws Exception ex + */ + @Test + public void testReadWriteUserPutInputPortThroughInheritedPolicy() throws Exception { + final PortEntity entity = createInputPort(NiFiTestAuthorizer.NO_POLICY_COMPONENT_NAME); + + final String updatedName = "Updated name" + count++; + + // attempt to update the name + final long version = entity.getRevision().getVersion(); + entity.getRevision().setClientId(READ_WRITE_CLIENT_ID); + entity.getComponent().setName(updatedName); + + // perform the request + final ClientResponse response = updateInputPort(helper.getReadWriteUser(), entity); + + // ensure successful response + assertEquals(200, response.getStatus()); + + // get the response + final PortEntity responseEntity = response.getEntity(PortEntity.class); + + // verify + assertEquals(AccessControlHelper.READ_WRITE_CLIENT_ID, responseEntity.getRevision().getClientId()); + assertEquals(version + 1, responseEntity.getRevision().getVersion().longValue()); + assertEquals(updatedName, responseEntity.getComponent().getName()); + } + + /** + * Ensures the WRITE user can put an input port. + * + * @throws Exception ex + */ + @Test + public void testWriteUserPutInputPort() throws Exception { + final PortEntity entity = getRandomInputPort(helper.getWriteUser()); + assertFalse(entity.getAccessPolicy().getCanRead()); + assertTrue(entity.getAccessPolicy().getCanWrite()); + assertNull(entity.getComponent()); + + final String updatedName = "Updated Name" + count++; + + // attempt to update the name + final PortDTO requestDto = new PortDTO(); + requestDto.setId(entity.getId()); + requestDto.setName(updatedName); + + final long version = entity.getRevision().getVersion(); + final RevisionDTO requestRevision = new RevisionDTO(); + requestRevision.setVersion(version); + requestRevision.setClientId(AccessControlHelper.WRITE_CLIENT_ID); + + final PortEntity requestEntity = new PortEntity(); + requestEntity.setId(entity.getId()); + requestEntity.setRevision(requestRevision); + requestEntity.setComponent(requestDto); + + // perform the request + final ClientResponse response = updateInputPort(helper.getWriteUser(), requestEntity); + + // ensure successful response + assertEquals(200, response.getStatus()); + + // get the response + final PortEntity responseEntity = response.getEntity(PortEntity.class); + + // verify + assertEquals(WRITE_CLIENT_ID, responseEntity.getRevision().getClientId()); + assertEquals(version + 1, responseEntity.getRevision().getVersion().longValue()); + } + + /** + * Ensures the NONE user cannot put an input port. + * + * @throws Exception ex + */ + @Test + public void testNoneUserPutInputPort() throws Exception { + final PortEntity entity = getRandomInputPort(helper.getNoneUser()); + assertFalse(entity.getAccessPolicy().getCanRead()); + assertFalse(entity.getAccessPolicy().getCanWrite()); + assertNull(entity.getComponent()); + + final String updatedName = "Updated Name" + count++; + + // attempt to update the name + final PortDTO requestDto = new PortDTO(); + requestDto.setId(entity.getId()); + requestDto.setName(updatedName); + + final long version = entity.getRevision().getVersion(); + final RevisionDTO requestRevision = new RevisionDTO(); + requestRevision.setVersion(version); + requestRevision.setClientId(AccessControlHelper.NONE_CLIENT_ID); + + final PortEntity requestEntity = new PortEntity(); + requestEntity.setId(entity.getId()); + requestEntity.setRevision(requestRevision); + requestEntity.setComponent(requestDto); + + // perform the request + final ClientResponse response = updateInputPort(helper.getNoneUser(), requestEntity); + + // ensure forbidden response + assertEquals(403, response.getStatus()); + } + + /** + * Ensures the READ user cannot delete an input port. + * + * @throws Exception ex + */ + @Test + public void testReadUserDeleteInputPort() throws Exception { + verifyDelete(helper.getReadUser(), AccessControlHelper.READ_CLIENT_ID, 403); + } + + /** + * Ensures the READ WRITE user can delete an input port. + * + * @throws Exception ex + */ + @Test + public void testReadWriteUserDeleteInputPort() throws Exception { + verifyDelete(helper.getReadWriteUser(), AccessControlHelper.READ_WRITE_CLIENT_ID, 200); + } + + /** + * Ensures the WRITE user can delete an input port. + * + * @throws Exception ex + */ + @Test + public void testWriteUserDeleteInputPort() throws Exception { + verifyDelete(helper.getWriteUser(), AccessControlHelper.WRITE_CLIENT_ID, 200); + } + + /** + * Ensures the NONE user can delete an input port. + * + * @throws Exception ex + */ + @Test + public void testNoneUserDeleteInputPort() throws Exception { + verifyDelete(helper.getNoneUser(), NONE_CLIENT_ID, 403); + } + + private PortEntity getRandomInputPort(final NiFiTestUser user) throws Exception { + final String url = helper.getBaseUrl() + "/flow/process-groups/root"; + + // get the input ports + final ClientResponse response = user.testGet(url); + + // ensure the response was successful + assertEquals(200, response.getStatus()); + + // unmarshal + final ProcessGroupFlowEntity flowEntity = response.getEntity(ProcessGroupFlowEntity.class); + final FlowDTO flowDto = flowEntity.getProcessGroupFlow().getFlow(); + final Set<PortEntity> inputPorts = flowDto.getInputPorts(); + + // ensure the correct number of input ports + assertFalse(inputPorts.isEmpty()); + + // use the first input port as the target + Iterator<PortEntity> inputPortIter = inputPorts.iterator(); + assertTrue(inputPortIter.hasNext()); + return inputPortIter.next(); + } + + private ClientResponse updateInputPort(final NiFiTestUser user, final PortEntity entity) throws Exception { + final String url = helper.getBaseUrl() + "/input-ports/" + entity.getId(); + + // perform the request + return user.testPut(url, entity); + } + + private PortEntity createInputPort(final String name) throws Exception { + String url = helper.getBaseUrl() + "/process-groups/root/input-ports"; + + final String updatedName = name + count++; + + // create the input port + PortDTO inputPort = new PortDTO(); + inputPort.setName(updatedName); + + // create the revision + final RevisionDTO revision = new RevisionDTO(); + revision.setClientId(READ_WRITE_CLIENT_ID); + revision.setVersion(0L); + + // create the entity body + PortEntity entity = new PortEntity(); + entity.setRevision(revision); + entity.setComponent(inputPort); + + // perform the request + ClientResponse response = helper.getReadWriteUser().testPost(url, entity); + + // ensure the request is successful + assertEquals(201, response.getStatus()); + + // get the entity body + entity = response.getEntity(PortEntity.class); + + // verify creation + inputPort = entity.getComponent(); + assertEquals(updatedName, inputPort.getName()); + + // get the input port + return entity; + } + + private void verifyDelete(final NiFiTestUser user, final String clientId, final int responseCode) throws Exception { + final PortEntity entity = createInputPort("Copy"); + + // create the entity body + final Map<String, String> queryParams = new HashMap<>(); + queryParams.put("version", String.valueOf(entity.getRevision().getVersion())); + queryParams.put("clientId", clientId); + + // perform the request + ClientResponse response = user.testDelete(entity.getComponent().getUri(), queryParams); + + // ensure the request is failed with a forbidden status code + assertEquals(responseCode, response.getStatus()); + } + + @AfterClass + public static void cleanup() throws Exception { + helper.cleanup(); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/f0811ca4/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITLabelAccessControl.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITLabelAccessControl.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITLabelAccessControl.java new file mode 100644 index 0000000..3a44d53 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITLabelAccessControl.java @@ -0,0 +1,402 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.nifi.integration.accesscontrol; + +import com.sun.jersey.api.client.ClientResponse; +import org.apache.nifi.integration.util.NiFiTestAuthorizer; +import org.apache.nifi.integration.util.NiFiTestUser; +import org.apache.nifi.web.api.dto.LabelDTO; +import org.apache.nifi.web.api.dto.RevisionDTO; +import org.apache.nifi.web.api.dto.flow.FlowDTO; +import org.apache.nifi.web.api.entity.LabelEntity; +import org.apache.nifi.web.api.entity.ProcessGroupFlowEntity; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import static org.apache.nifi.integration.accesscontrol.AccessControlHelper.NONE_CLIENT_ID; +import static org.apache.nifi.integration.accesscontrol.AccessControlHelper.READ_CLIENT_ID; +import static org.apache.nifi.integration.accesscontrol.AccessControlHelper.READ_WRITE_CLIENT_ID; +import static org.apache.nifi.integration.accesscontrol.AccessControlHelper.WRITE_CLIENT_ID; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Access control test for labels. + */ +public class ITLabelAccessControl { + + private static final String FLOW_XML_PATH = "target/test-classes/access-control/flow-labels.xml"; + + private static AccessControlHelper helper; + + @BeforeClass + public static void setup() throws Exception { + helper = new AccessControlHelper(FLOW_XML_PATH); + } + + /** + * Ensures the READ user can get a label. + * + * @throws Exception ex + */ + @Test + public void testReadUserGetLabel() throws Exception { + final LabelEntity entity = getRandomLabel(helper.getReadUser()); + assertTrue(entity.getAccessPolicy().getCanRead()); + assertFalse(entity.getAccessPolicy().getCanWrite()); + assertNotNull(entity.getComponent()); + } + + /** + * Ensures the READ WRITE user can get a label. + * + * @throws Exception ex + */ + @Test + public void testReadWriteUserGetLabel() throws Exception { + final LabelEntity entity = getRandomLabel(helper.getReadWriteUser()); + assertTrue(entity.getAccessPolicy().getCanRead()); + assertTrue(entity.getAccessPolicy().getCanWrite()); + assertNotNull(entity.getComponent()); + } + + /** + * Ensures the WRITE user can get a label. + * + * @throws Exception ex + */ + @Test + public void testWriteUserGetLabel() throws Exception { + final LabelEntity entity = getRandomLabel(helper.getWriteUser()); + assertFalse(entity.getAccessPolicy().getCanRead()); + assertTrue(entity.getAccessPolicy().getCanWrite()); + assertNull(entity.getComponent()); + } + + /** + * Ensures the NONE user can get a label. + * + * @throws Exception ex + */ + @Test + public void testNoneUserGetLabel() throws Exception { + final LabelEntity entity = getRandomLabel(helper.getNoneUser()); + assertFalse(entity.getAccessPolicy().getCanRead()); + assertFalse(entity.getAccessPolicy().getCanWrite()); + assertNull(entity.getComponent()); + } + + /** + * Ensures the READ user cannot put a label. + * + * @throws Exception ex + */ + @Test + public void testReadUserPutLabel() throws Exception { + final LabelEntity entity = getRandomLabel(helper.getReadUser()); + assertTrue(entity.getAccessPolicy().getCanRead()); + assertFalse(entity.getAccessPolicy().getCanWrite()); + assertNotNull(entity.getComponent()); + + // attempt update the name + entity.getRevision().setClientId(READ_CLIENT_ID); + entity.getComponent().setLabel("Updated Label"); + + // perform the request + final ClientResponse response = updateLabel(helper.getReadUser(), entity); + + // ensure forbidden response + assertEquals(403, response.getStatus()); + } + + /** + * Ensures the READ_WRITE user can put a label. + * + * @throws Exception ex + */ + @Test + public void testReadWriteUserPutLabel() throws Exception { + final LabelEntity entity = getRandomLabel(helper.getReadWriteUser()); + assertTrue(entity.getAccessPolicy().getCanRead()); + assertTrue(entity.getAccessPolicy().getCanWrite()); + assertNotNull(entity.getComponent()); + + final String updatedLabel = "Updated Name"; + + // attempt to update the name + final long version = entity.getRevision().getVersion(); + entity.getRevision().setClientId(AccessControlHelper.READ_WRITE_CLIENT_ID); + entity.getComponent().setLabel(updatedLabel); + + // perform the request + final ClientResponse response = updateLabel(helper.getReadWriteUser(), entity); + + // ensure successful response + assertEquals(200, response.getStatus()); + + // get the response + final LabelEntity responseEntity = response.getEntity(LabelEntity.class); + + // verify + assertEquals(READ_WRITE_CLIENT_ID, responseEntity.getRevision().getClientId()); + assertEquals(version + 1, responseEntity.getRevision().getVersion().longValue()); + assertEquals(updatedLabel, responseEntity.getComponent().getLabel()); + } + + /** + * Ensures the READ_WRITE user can put a label. + * + * @throws Exception ex + */ + @Test + public void testReadWriteUserPutLabelThroughInheritedPolicy() throws Exception { + final LabelEntity entity = createLabel(NiFiTestAuthorizer.NO_POLICY_COMPONENT_NAME); + + final String updatedLabel = "Updated name"; + + // attempt to update the name + final long version = entity.getRevision().getVersion(); + entity.getRevision().setClientId(READ_WRITE_CLIENT_ID); + entity.getComponent().setLabel(updatedLabel); + + // perform the request + final ClientResponse response = updateLabel(helper.getReadWriteUser(), entity); + + // ensure successful response + assertEquals(200, response.getStatus()); + + // get the response + final LabelEntity responseEntity = response.getEntity(LabelEntity.class); + + // verify + assertEquals(AccessControlHelper.READ_WRITE_CLIENT_ID, responseEntity.getRevision().getClientId()); + assertEquals(version + 1, responseEntity.getRevision().getVersion().longValue()); + assertEquals(updatedLabel, responseEntity.getComponent().getLabel()); + } + + /** + * Ensures the WRITE user can put a label. + * + * @throws Exception ex + */ + @Test + public void testWriteUserPutLabel() throws Exception { + final LabelEntity entity = getRandomLabel(helper.getWriteUser()); + assertFalse(entity.getAccessPolicy().getCanRead()); + assertTrue(entity.getAccessPolicy().getCanWrite()); + assertNull(entity.getComponent()); + + final String updatedLabel = "Updated Name"; + + // attempt to update the label + final LabelDTO requestDto = new LabelDTO(); + requestDto.setId(entity.getId()); + requestDto.setLabel(updatedLabel); + + final long version = entity.getRevision().getVersion(); + final RevisionDTO requestRevision = new RevisionDTO(); + requestRevision.setVersion(version); + requestRevision.setClientId(AccessControlHelper.WRITE_CLIENT_ID); + + final LabelEntity requestEntity = new LabelEntity(); + requestEntity.setId(entity.getId()); + requestEntity.setRevision(requestRevision); + requestEntity.setComponent(requestDto); + + // perform the request + final ClientResponse response = updateLabel(helper.getWriteUser(), requestEntity); + + // ensure successful response + assertEquals(200, response.getStatus()); + + // get the response + final LabelEntity responseEntity = response.getEntity(LabelEntity.class); + + // verify + assertEquals(WRITE_CLIENT_ID, responseEntity.getRevision().getClientId()); + assertEquals(version + 1, responseEntity.getRevision().getVersion().longValue()); + } + + /** + * Ensures the NONE user cannot put a label. + * + * @throws Exception ex + */ + @Test + public void testNoneUserPutLabel() throws Exception { + final LabelEntity entity = getRandomLabel(helper.getNoneUser()); + assertFalse(entity.getAccessPolicy().getCanRead()); + assertFalse(entity.getAccessPolicy().getCanWrite()); + assertNull(entity.getComponent()); + + final String updatedName = "Updated Name"; + + // attempt to update the name + final LabelDTO requestDto = new LabelDTO(); + requestDto.setId(entity.getId()); + requestDto.setLabel(updatedName); + + final long version = entity.getRevision().getVersion(); + final RevisionDTO requestRevision = new RevisionDTO(); + requestRevision.setVersion(version); + requestRevision.setClientId(AccessControlHelper.NONE_CLIENT_ID); + + final LabelEntity requestEntity = new LabelEntity(); + requestEntity.setId(entity.getId()); + requestEntity.setRevision(requestRevision); + requestEntity.setComponent(requestDto); + + // perform the request + final ClientResponse response = updateLabel(helper.getNoneUser(), requestEntity); + + // ensure forbidden response + assertEquals(403, response.getStatus()); + } + + /** + * Ensures the READ user cannot delete a label. + * + * @throws Exception ex + */ + @Test + public void testReadUserDeleteLabel() throws Exception { + verifyDelete(helper.getReadUser(), AccessControlHelper.READ_CLIENT_ID, 403); + } + + /** + * Ensures the READ WRITE user can delete a label. + * + * @throws Exception ex + */ + @Test + public void testReadWriteUserDeleteLabel() throws Exception { + verifyDelete(helper.getReadWriteUser(), AccessControlHelper.READ_WRITE_CLIENT_ID, 200); + } + + /** + * Ensures the WRITE user can delete a label. + * + * @throws Exception ex + */ + @Test + public void testWriteUserDeleteLabel() throws Exception { + verifyDelete(helper.getWriteUser(), AccessControlHelper.WRITE_CLIENT_ID, 200); + } + + /** + * Ensures the NONE user can delete a label. + * + * @throws Exception ex + */ + @Test + public void testNoneUserDeleteLabel() throws Exception { + verifyDelete(helper.getNoneUser(), NONE_CLIENT_ID, 403); + } + + private LabelEntity getRandomLabel(final NiFiTestUser user) throws Exception { + final String url = helper.getBaseUrl() + "/flow/process-groups/root"; + + // get the labels + final ClientResponse response = user.testGet(url); + + // ensure the response was successful + assertEquals(200, response.getStatus()); + + // unmarshal + final ProcessGroupFlowEntity flowEntity = response.getEntity(ProcessGroupFlowEntity.class); + final FlowDTO flowDto = flowEntity.getProcessGroupFlow().getFlow(); + final Set<LabelEntity> labels = flowDto.getLabels(); + + // ensure the correct number of labels + assertFalse(labels.isEmpty()); + + // use the first label as the target + Iterator<LabelEntity> labelIter = labels.iterator(); + assertTrue(labelIter.hasNext()); + return labelIter.next(); + } + + private ClientResponse updateLabel(final NiFiTestUser user, final LabelEntity entity) throws Exception { + final String url = helper.getBaseUrl() + "/labels/" + entity.getId(); + + // perform the request + return user.testPut(url, entity); + } + + private LabelEntity createLabel(final String name) throws Exception { + String url = helper.getBaseUrl() + "/process-groups/root/labels"; + + // create the label + LabelDTO label = new LabelDTO(); + label.setLabel(name); + + // create the revision + final RevisionDTO revision = new RevisionDTO(); + revision.setClientId(READ_WRITE_CLIENT_ID); + revision.setVersion(0L); + + // create the entity body + LabelEntity entity = new LabelEntity(); + entity.setRevision(revision); + entity.setComponent(label); + + // perform the request + ClientResponse response = helper.getReadWriteUser().testPost(url, entity); + + // ensure the request is successful + assertEquals(201, response.getStatus()); + + // get the entity body + entity = response.getEntity(LabelEntity.class); + + // verify creation + label = entity.getComponent(); + assertEquals(name, label.getLabel()); + + // get the label id + return entity; + } + + private void verifyDelete(final NiFiTestUser user, final String clientId, final int responseCode) throws Exception { + final LabelEntity entity = createLabel("Copy"); + + // create the entity body + final Map<String, String> queryParams = new HashMap<>(); + queryParams.put("version", String.valueOf(entity.getRevision().getVersion())); + queryParams.put("clientId", clientId); + + // perform the request + ClientResponse response = user.testDelete(entity.getComponent().getUri(), queryParams); + + // ensure the request is failed with a forbidden status code + assertEquals(responseCode, response.getStatus()); + } + + @AfterClass + public static void cleanup() throws Exception { + helper.cleanup(); + } +}
