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();
+    }
+}

Reply via email to