You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by al...@apache.org on 2016/11/21 20:31:18 UTC

[1/3] nifi git commit: NIFI-3050: Implemented access control logic for restricted components.

Repository: nifi
Updated Branches:
  refs/heads/master eb5abf809 -> 7f5eabd60


http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-hadoop-bundle/nifi-hdfs-processors/src/main/java/org/apache/nifi/processors/hadoop/FetchHDFS.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-hadoop-bundle/nifi-hdfs-processors/src/main/java/org/apache/nifi/processors/hadoop/FetchHDFS.java b/nifi-nar-bundles/nifi-hadoop-bundle/nifi-hdfs-processors/src/main/java/org/apache/nifi/processors/hadoop/FetchHDFS.java
index cd5f76c..97039e2 100644
--- a/nifi-nar-bundles/nifi-hadoop-bundle/nifi-hdfs-processors/src/main/java/org/apache/nifi/processors/hadoop/FetchHDFS.java
+++ b/nifi-nar-bundles/nifi-hadoop-bundle/nifi-hdfs-processors/src/main/java/org/apache/nifi/processors/hadoop/FetchHDFS.java
@@ -26,6 +26,7 @@ import org.apache.hadoop.io.compress.CompressionCodecFactory;
 import org.apache.hadoop.security.AccessControlException;
 import org.apache.nifi.annotation.behavior.InputRequirement;
 import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.behavior.SupportsBatching;
 import org.apache.nifi.annotation.behavior.WritesAttribute;
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
@@ -53,12 +54,13 @@ import java.util.concurrent.TimeUnit;
 
 @SupportsBatching
 @InputRequirement(Requirement.INPUT_REQUIRED)
-@Tags({"hadoop", "hdfs", "get", "ingest", "fetch", "source"})
+@Tags({"hadoop", "hdfs", "get", "ingest", "fetch", "source", "restricted"})
 @CapabilityDescription("Retrieves a file from HDFS. The content of the incoming FlowFile is replaced by the content of the file in HDFS. "
         + "The file in HDFS is left intact without any changes being made to it.")
 @WritesAttribute(attribute="hdfs.failure.reason", description="When a FlowFile is routed to 'failure', this attribute is added indicating why the file could "
         + "not be fetched from HDFS")
 @SeeAlso({ListHDFS.class, GetHDFS.class, PutHDFS.class})
+@Restricted("Provides operator the ability to retrieve any file that NiFi has access to in HDFS or the local filesystem.")
 public class FetchHDFS extends AbstractHadoopProcessor {
 
     static final PropertyDescriptor FILENAME = new PropertyDescriptor.Builder()

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-hadoop-bundle/nifi-hdfs-processors/src/main/java/org/apache/nifi/processors/hadoop/GetHDFS.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-hadoop-bundle/nifi-hdfs-processors/src/main/java/org/apache/nifi/processors/hadoop/GetHDFS.java b/nifi-nar-bundles/nifi-hadoop-bundle/nifi-hdfs-processors/src/main/java/org/apache/nifi/processors/hadoop/GetHDFS.java
index 24de0c4..7357d35 100644
--- a/nifi-nar-bundles/nifi-hadoop-bundle/nifi-hdfs-processors/src/main/java/org/apache/nifi/processors/hadoop/GetHDFS.java
+++ b/nifi-nar-bundles/nifi-hadoop-bundle/nifi-hdfs-processors/src/main/java/org/apache/nifi/processors/hadoop/GetHDFS.java
@@ -27,6 +27,7 @@ import org.apache.hadoop.io.compress.CompressionCodec;
 import org.apache.hadoop.io.compress.CompressionCodecFactory;
 import org.apache.nifi.annotation.behavior.InputRequirement;
 import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.behavior.TriggerWhenEmpty;
 import org.apache.nifi.annotation.behavior.WritesAttribute;
 import org.apache.nifi.annotation.behavior.WritesAttributes;
@@ -65,7 +66,7 @@ import java.util.regex.Pattern;
 
 @TriggerWhenEmpty
 @InputRequirement(Requirement.INPUT_FORBIDDEN)
-@Tags({"hadoop", "HDFS", "get", "fetch", "ingest", "source", "filesystem"})
+@Tags({"hadoop", "HDFS", "get", "fetch", "ingest", "source", "filesystem", "restricted"})
 @CapabilityDescription("Fetch files from Hadoop Distributed File System (HDFS) into FlowFiles. This Processor will delete the file from HDFS after fetching it.")
 @WritesAttributes({
     @WritesAttribute(attribute = "filename", description = "The name of the file that was read from HDFS."),
@@ -73,6 +74,7 @@ import java.util.regex.Pattern;
             + "is set to /tmp, then files picked up from /tmp will have the path attribute set to \"./\". If the Recurse Subdirectories property is set to true and "
             + "a file is picked up from /tmp/abc/1/2/3, then the path attribute will be set to \"abc/1/2/3\".") })
 @SeeAlso({PutHDFS.class, ListHDFS.class})
+@Restricted("Provides operator the ability to retrieve and delete any file that NiFi has access to in HDFS or the local filesystem.")
 public class GetHDFS extends AbstractHadoopProcessor {
 
     public static final String BUFFER_SIZE_KEY = "io.file.buffer.size";

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-hadoop-bundle/nifi-hdfs-processors/src/main/java/org/apache/nifi/processors/hadoop/PutHDFS.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-hadoop-bundle/nifi-hdfs-processors/src/main/java/org/apache/nifi/processors/hadoop/PutHDFS.java b/nifi-nar-bundles/nifi-hadoop-bundle/nifi-hdfs-processors/src/main/java/org/apache/nifi/processors/hadoop/PutHDFS.java
index f8841d6..5fbe577 100644
--- a/nifi-nar-bundles/nifi-hadoop-bundle/nifi-hdfs-processors/src/main/java/org/apache/nifi/processors/hadoop/PutHDFS.java
+++ b/nifi-nar-bundles/nifi-hadoop-bundle/nifi-hdfs-processors/src/main/java/org/apache/nifi/processors/hadoop/PutHDFS.java
@@ -26,6 +26,7 @@ import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.nifi.annotation.behavior.InputRequirement;
 import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
 import org.apache.nifi.annotation.behavior.ReadsAttribute;
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.behavior.WritesAttribute;
 import org.apache.nifi.annotation.behavior.WritesAttributes;
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
@@ -67,7 +68,7 @@ import java.util.concurrent.TimeUnit;
  * This processor copies FlowFiles to HDFS.
  */
 @InputRequirement(Requirement.INPUT_REQUIRED)
-@Tags({"hadoop", "HDFS", "put", "copy", "filesystem"})
+@Tags({"hadoop", "HDFS", "put", "copy", "filesystem", "restricted"})
 @CapabilityDescription("Write FlowFile data to Hadoop Distributed File System (HDFS)")
 @ReadsAttribute(attribute = "filename", description = "The name of the file written to HDFS comes from the value of this attribute.")
 @WritesAttributes({
@@ -75,6 +76,7 @@ import java.util.concurrent.TimeUnit;
         @WritesAttribute(attribute = "absolute.hdfs.path", description = "The absolute path to the file on HDFS is stored in this attribute.")
 })
 @SeeAlso(GetHDFS.class)
+@Restricted("Provides operator the ability to write to any file that NiFi has access to in HDFS or the local filesystem.")
 public class PutHDFS extends AbstractHadoopProcessor {
 
     public static final String REPLACE_RESOLUTION = "replace";

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ExecuteScript.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ExecuteScript.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ExecuteScript.java
index b863a42..b2bc8ef 100644
--- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ExecuteScript.java
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ExecuteScript.java
@@ -16,25 +16,14 @@
  */
 package org.apache.nifi.processors.script;
 
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.script.Bindings;
-import javax.script.ScriptContext;
-import javax.script.ScriptEngine;
-import javax.script.ScriptException;
-import javax.script.SimpleBindings;
 import org.apache.commons.io.IOUtils;
 import org.apache.nifi.annotation.behavior.DynamicProperty;
-import org.apache.nifi.components.PropertyDescriptor;
-import org.apache.nifi.logging.ComponentLog;
-import org.apache.nifi.annotation.lifecycle.OnScheduled;
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
 import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnScheduled;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.logging.ComponentLog;
 import org.apache.nifi.processor.ProcessContext;
 import org.apache.nifi.processor.ProcessSession;
 import org.apache.nifi.processor.ProcessSessionFactory;
@@ -43,7 +32,20 @@ import org.apache.nifi.processor.exception.ProcessException;
 import org.apache.nifi.processor.util.StandardValidators;
 import org.apache.nifi.util.StringUtils;
 
-@Tags({"script", "execute", "groovy", "python", "jython", "jruby", "ruby", "javascript", "js", "lua", "luaj"})
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+import javax.script.SimpleBindings;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@Tags({"script", "execute", "groovy", "python", "jython", "jruby", "ruby", "javascript", "js", "lua", "luaj", "restricted"})
 @CapabilityDescription("Experimental - Executes a script given the flow file and a process session.  The script is responsible for "
         + "handling the incoming flow file (transfer to SUCCESS or remove, e.g.) as well as any flow files created by "
         + "the script. If the handling is incomplete or incorrect, the session will be rolled back. Experimental: "
@@ -54,6 +56,7 @@ import org.apache.nifi.util.StringUtils;
         supportsExpressionLanguage = true,
         description = "Updates a script engine property specified by the Dynamic Property's key with the value "
                 + "specified by the Dynamic Property's value")
+@Restricted("Provides operator the ability to execute arbitrary code assuming all permissions that NiFi has.")
 public class ExecuteScript extends AbstractScriptProcessor {
 
     private String scriptToRun = null;

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/InvokeScriptedProcessor.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/InvokeScriptedProcessor.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/InvokeScriptedProcessor.java
index fa65994..53219ac 100644
--- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/InvokeScriptedProcessor.java
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/InvokeScriptedProcessor.java
@@ -16,24 +16,10 @@
  */
 package org.apache.nifi.processors.script;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicReference;
-
-import javax.script.Invocable;
-import javax.script.ScriptEngine;
-import javax.script.ScriptException;
-
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.annotation.behavior.DynamicProperty;
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
 import org.apache.nifi.annotation.documentation.SeeAlso;
 import org.apache.nifi.annotation.documentation.Tags;
@@ -53,7 +39,21 @@ import org.apache.nifi.processor.Relationship;
 import org.apache.nifi.processor.exception.ProcessException;
 import org.apache.nifi.processor.util.StandardValidators;
 
-@Tags({"script", "invoke", "groovy", "python", "jython", "jruby", "ruby", "javascript", "js", "lua", "luaj"})
+import javax.script.Invocable;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+@Tags({"script", "invoke", "groovy", "python", "jython", "jruby", "ruby", "javascript", "js", "lua", "luaj", "restricted"})
 @CapabilityDescription("Experimental - Invokes a script engine for a Processor defined in the given script. The script must define "
         + "a valid class that implements the Processor interface, and it must set a variable 'processor' to an instance of "
         + "the class. Processor methods such as onTrigger() will be delegated to the scripted Processor instance. Also any "
@@ -62,6 +62,7 @@ import org.apache.nifi.processor.util.StandardValidators;
 @DynamicProperty(name = "A script engine property to update", value = "The value to set it to", supportsExpressionLanguage = true,
         description = "Updates a script engine property specified by the Dynamic Property's key with the value specified by the Dynamic Property's value")
 @SeeAlso({ExecuteScript.class})
+@Restricted("Provides operator the ability to execute arbitrary code assuming all permissions that NiFi has.")
 public class InvokeScriptedProcessor extends AbstractScriptProcessor {
 
     private final AtomicReference<Processor> processor = new AtomicReference<>();

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/main/java/org/apache/nifi/reporting/SiteToSiteProvenanceReportingTask.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/main/java/org/apache/nifi/reporting/SiteToSiteProvenanceReportingTask.java b/nifi-nar-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/main/java/org/apache/nifi/reporting/SiteToSiteProvenanceReportingTask.java
index ef10a21..81a4ea4 100644
--- a/nifi-nar-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/main/java/org/apache/nifi/reporting/SiteToSiteProvenanceReportingTask.java
+++ b/nifi-nar-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/main/java/org/apache/nifi/reporting/SiteToSiteProvenanceReportingTask.java
@@ -17,6 +17,7 @@
 
 package org.apache.nifi.reporting;
 
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.behavior.Stateful;
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
 import org.apache.nifi.annotation.documentation.Tags;
@@ -55,9 +56,10 @@ import java.util.TimeZone;
 import java.util.UUID;
 import java.util.concurrent.TimeUnit;
 
-@Tags({"provenance", "lineage", "tracking", "site", "site to site"})
+@Tags({"provenance", "lineage", "tracking", "site", "site to site", "restricted"})
 @CapabilityDescription("Publishes Provenance events using the Site To Site protocol.")
 @Stateful(scopes = Scope.LOCAL, description = "Stores the Reporting Task's last event Id so that on restart the task knows where it left off.")
+@Restricted("Provides operator the ability send sensitive details contained in Provenance events to any external system.")
 public class SiteToSiteProvenanceReportingTask extends AbstractSiteToSiteReportingTask {
 
     static final String TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ExecuteProcess.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ExecuteProcess.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ExecuteProcess.java
index cdaec8f..4cbe3a1 100644
--- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ExecuteProcess.java
+++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ExecuteProcess.java
@@ -16,6 +16,28 @@
  */
 package org.apache.nifi.processors.standard;
 
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.annotation.behavior.DynamicProperty;
+import org.apache.nifi.annotation.behavior.InputRequirement;
+import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
+import org.apache.nifi.annotation.behavior.Restricted;
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnScheduled;
+import org.apache.nifi.annotation.lifecycle.OnUnscheduled;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.Validator;
+import org.apache.nifi.flowfile.FlowFile;
+import org.apache.nifi.logging.ComponentLog;
+import org.apache.nifi.processor.AbstractProcessor;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.ProcessSession;
+import org.apache.nifi.processor.Relationship;
+import org.apache.nifi.processor.exception.ProcessException;
+import org.apache.nifi.processor.io.OutputStreamCallback;
+import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.processors.standard.util.ArgumentUtils;
+
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.BufferedReader;
@@ -41,33 +63,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
-import org.apache.commons.lang3.StringUtils;
-import org.apache.nifi.annotation.behavior.DynamicProperty;
-import org.apache.nifi.annotation.behavior.InputRequirement;
-import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
-import org.apache.nifi.annotation.documentation.CapabilityDescription;
-import org.apache.nifi.annotation.documentation.Tags;
-import org.apache.nifi.annotation.lifecycle.OnScheduled;
-import org.apache.nifi.annotation.lifecycle.OnUnscheduled;
-import org.apache.nifi.components.PropertyDescriptor;
-import org.apache.nifi.components.Validator;
-import org.apache.nifi.flowfile.FlowFile;
-import org.apache.nifi.logging.ComponentLog;
-import org.apache.nifi.processor.AbstractProcessor;
-import org.apache.nifi.processor.ProcessContext;
-import org.apache.nifi.processor.ProcessSession;
-import org.apache.nifi.processor.Relationship;
-import org.apache.nifi.processor.exception.ProcessException;
-import org.apache.nifi.processor.io.OutputStreamCallback;
-import org.apache.nifi.processor.util.StandardValidators;
-import org.apache.nifi.processors.standard.util.ArgumentUtils;
-
 @InputRequirement(Requirement.INPUT_FORBIDDEN)
-@Tags({"command", "process", "source", "external", "invoke", "script"})
+@Tags({"command", "process", "source", "external", "invoke", "script", "restricted"})
 @CapabilityDescription("Runs an operating system command specified by the user and writes the output of that command to a FlowFile. If the command is expected "
         + "to be long-running, the Processor can output the partial data on a specified interval. When this option is used, the output is expected to be in textual "
         + "format, as it typically does not make sense to split binary data on arbitrary time-based intervals.")
 @DynamicProperty(name = "An environment variable name", value = "An environment variable value", description = "These environment variables are passed to the process spawned by this Processor")
+@Restricted("Provides operator the ability to execute arbitrary code assuming all permissions that NiFi has.")
 public class ExecuteProcess extends AbstractProcessor {
 
     public static final PropertyDescriptor COMMAND = new PropertyDescriptor.Builder()

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ExecuteStreamCommand.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ExecuteStreamCommand.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ExecuteStreamCommand.java
index 4654a22..13e3c58 100644
--- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ExecuteStreamCommand.java
+++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ExecuteStreamCommand.java
@@ -16,28 +16,13 @@
  */
 package org.apache.nifi.processors.standard;
 
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.lang.ProcessBuilder.Redirect;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicReference;
-
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.annotation.behavior.DynamicProperty;
 import org.apache.nifi.annotation.behavior.EventDriven;
 import org.apache.nifi.annotation.behavior.InputRequirement;
 import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.behavior.SupportsBatching;
 import org.apache.nifi.annotation.behavior.WritesAttribute;
 import org.apache.nifi.annotation.behavior.WritesAttributes;
@@ -65,6 +50,22 @@ import org.apache.nifi.stream.io.BufferedInputStream;
 import org.apache.nifi.stream.io.BufferedOutputStream;
 import org.apache.nifi.stream.io.StreamUtils;
 
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.lang.ProcessBuilder.Redirect;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
 /**
  * <p>
  * This processor executes an external command on the contents of a flow file, and creates a new flow file with the results of the command.
@@ -124,7 +125,7 @@ import org.apache.nifi.stream.io.StreamUtils;
 @EventDriven
 @SupportsBatching
 @InputRequirement(Requirement.INPUT_REQUIRED)
-@Tags({"command execution", "command", "stream", "execute"})
+@Tags({"command execution", "command", "stream", "execute", "restricted"})
 @CapabilityDescription("Executes an external command on the contents of a flow file, and creates a new flow file with the results of the command.")
 @DynamicProperty(name = "An environment variable name", value = "An environment variable value", description = "These environment variables are passed to the process spawned by this Processor")
 @WritesAttributes({
@@ -132,6 +133,7 @@ import org.apache.nifi.stream.io.StreamUtils;
     @WritesAttribute(attribute = "execution.command.args", description = "The semi-colon delimited list of arguments"),
     @WritesAttribute(attribute = "execution.status", description = "The exit status code returned from executing the command"),
     @WritesAttribute(attribute = "execution.error", description = "Any error messages returned from executing the command")})
+@Restricted("Provides operator the ability to execute arbitrary code assuming all permissions that NiFi has.")
 public class ExecuteStreamCommand extends AbstractProcessor {
 
     public static final Relationship ORIGINAL_RELATIONSHIP = new Relationship.Builder()

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/FetchFile.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/FetchFile.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/FetchFile.java
index 7c2c415..b91999e 100644
--- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/FetchFile.java
+++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/FetchFile.java
@@ -17,24 +17,10 @@
 
 package org.apache.nifi.processors.standard;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.nio.file.CopyOption;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardCopyOption;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.TimeUnit;
-
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.annotation.behavior.InputRequirement;
 import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
 import org.apache.nifi.annotation.documentation.SeeAlso;
 import org.apache.nifi.annotation.documentation.Tags;
@@ -52,11 +38,27 @@ import org.apache.nifi.processor.exception.ProcessException;
 import org.apache.nifi.processor.util.StandardValidators;
 import org.apache.nifi.util.StopWatch;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.file.CopyOption;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
 @InputRequirement(Requirement.INPUT_REQUIRED)
-@Tags({"local", "files", "filesystem", "ingest", "ingress", "get", "source", "input"})
+@Tags({"local", "files", "filesystem", "ingest", "ingress", "get", "source", "input", "restricted"})
 @CapabilityDescription("Reads the contents of a file from disk and streams it into the contents of an incoming FlowFile. Once this is done, the file is optionally moved elsewhere or deleted "
     + "to help keep the file system organized.")
 @SeeAlso({GetFile.class, PutFile.class, ListFile.class})
+@Restricted("Provides operator the ability to read from and delete any file that NiFi has access to.")
 public class FetchFile extends AbstractProcessor {
     static final AllowableValue COMPLETION_NONE = new AllowableValue("None", "None", "Leave the file as-is");
     static final AllowableValue COMPLETION_MOVE = new AllowableValue("Move File", "Move File", "Moves the file to the directory specified by the <Move Destination Directory> property");

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/GetFile.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/GetFile.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/GetFile.java
index cdfb857..e5d2827 100644
--- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/GetFile.java
+++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/GetFile.java
@@ -16,6 +16,29 @@
  */
 package org.apache.nifi.processors.standard;
 
+import org.apache.nifi.annotation.behavior.InputRequirement;
+import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
+import org.apache.nifi.annotation.behavior.Restricted;
+import org.apache.nifi.annotation.behavior.TriggerWhenEmpty;
+import org.apache.nifi.annotation.behavior.WritesAttribute;
+import org.apache.nifi.annotation.behavior.WritesAttributes;
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.SeeAlso;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnScheduled;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.flowfile.FlowFile;
+import org.apache.nifi.flowfile.attributes.CoreAttributes;
+import org.apache.nifi.logging.ComponentLog;
+import org.apache.nifi.processor.AbstractProcessor;
+import org.apache.nifi.processor.DataUnit;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.ProcessSession;
+import org.apache.nifi.processor.ProcessorInitializationContext;
+import org.apache.nifi.processor.Relationship;
+import org.apache.nifi.processor.exception.ProcessException;
+import org.apache.nifi.processor.util.StandardValidators;
+
 import java.io.File;
 import java.io.FileFilter;
 import java.io.IOException;
@@ -48,31 +71,10 @@ import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.regex.Pattern;
-import org.apache.nifi.annotation.behavior.InputRequirement;
-import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
-import org.apache.nifi.annotation.behavior.TriggerWhenEmpty;
-import org.apache.nifi.annotation.behavior.WritesAttribute;
-import org.apache.nifi.annotation.behavior.WritesAttributes;
-import org.apache.nifi.annotation.documentation.CapabilityDescription;
-import org.apache.nifi.annotation.documentation.SeeAlso;
-import org.apache.nifi.annotation.documentation.Tags;
-import org.apache.nifi.annotation.lifecycle.OnScheduled;
-import org.apache.nifi.components.PropertyDescriptor;
-import org.apache.nifi.flowfile.FlowFile;
-import org.apache.nifi.flowfile.attributes.CoreAttributes;
-import org.apache.nifi.logging.ComponentLog;
-import org.apache.nifi.processor.AbstractProcessor;
-import org.apache.nifi.processor.DataUnit;
-import org.apache.nifi.processor.ProcessContext;
-import org.apache.nifi.processor.ProcessSession;
-import org.apache.nifi.processor.ProcessorInitializationContext;
-import org.apache.nifi.processor.Relationship;
-import org.apache.nifi.processor.exception.ProcessException;
-import org.apache.nifi.processor.util.StandardValidators;
 
 @TriggerWhenEmpty
 @InputRequirement(Requirement.INPUT_FORBIDDEN)
-@Tags({"local", "files", "filesystem", "ingest", "ingress", "get", "source", "input"})
+@Tags({"local", "files", "filesystem", "ingest", "ingress", "get", "source", "input", "restricted"})
 @CapabilityDescription("Creates FlowFiles from files in a directory.  NiFi will ignore files it doesn't have at least read permissions for.")
 @WritesAttributes({
     @WritesAttribute(attribute = "filename", description = "The filename is set to the name of the file on disk"),
@@ -91,6 +93,7 @@ import org.apache.nifi.processor.util.StandardValidators;
     @WritesAttribute(attribute = "absolute.path", description = "The full/absolute path from where a file was picked up. The current 'path' "
             + "attribute is still populated, but may be a relative path")})
 @SeeAlso({PutFile.class, FetchFile.class})
+@Restricted("Provides operator the ability to read from and delete any file that NiFi has access to.")
 public class GetFile extends AbstractProcessor {
 
     public static final PropertyDescriptor DIRECTORY = new PropertyDescriptor.Builder()

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ListFile.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ListFile.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ListFile.java
index d8e2044..1f5ccdb 100644
--- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ListFile.java
+++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ListFile.java
@@ -17,6 +17,27 @@
 
 package org.apache.nifi.processors.standard;
 
+import org.apache.nifi.annotation.behavior.InputRequirement;
+import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
+import org.apache.nifi.annotation.behavior.Stateful;
+import org.apache.nifi.annotation.behavior.TriggerSerially;
+import org.apache.nifi.annotation.behavior.WritesAttribute;
+import org.apache.nifi.annotation.behavior.WritesAttributes;
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.SeeAlso;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnScheduled;
+import org.apache.nifi.components.AllowableValue;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.state.Scope;
+import org.apache.nifi.flowfile.attributes.CoreAttributes;
+import org.apache.nifi.processor.DataUnit;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.ProcessorInitializationContext;
+import org.apache.nifi.processor.Relationship;
+import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.processors.standard.util.FileInfo;
+
 import java.io.File;
 import java.io.FileFilter;
 import java.io.IOException;
@@ -44,27 +65,6 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.regex.Pattern;
 
-import org.apache.nifi.annotation.behavior.InputRequirement;
-import org.apache.nifi.annotation.behavior.Stateful;
-import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
-import org.apache.nifi.annotation.behavior.TriggerSerially;
-import org.apache.nifi.annotation.behavior.WritesAttribute;
-import org.apache.nifi.annotation.behavior.WritesAttributes;
-import org.apache.nifi.annotation.documentation.CapabilityDescription;
-import org.apache.nifi.annotation.documentation.SeeAlso;
-import org.apache.nifi.annotation.documentation.Tags;
-import org.apache.nifi.annotation.lifecycle.OnScheduled;
-import org.apache.nifi.components.AllowableValue;
-import org.apache.nifi.components.PropertyDescriptor;
-import org.apache.nifi.components.state.Scope;
-import org.apache.nifi.flowfile.attributes.CoreAttributes;
-import org.apache.nifi.processor.DataUnit;
-import org.apache.nifi.processor.ProcessContext;
-import org.apache.nifi.processor.ProcessorInitializationContext;
-import org.apache.nifi.processor.Relationship;
-import org.apache.nifi.processor.util.StandardValidators;
-import org.apache.nifi.processors.standard.util.FileInfo;
-
 @TriggerSerially
 @InputRequirement(Requirement.INPUT_FORBIDDEN)
 @Tags({"file", "get", "list", "ingest", "source", "filesystem"})

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/PutFile.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/PutFile.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/PutFile.java
index 8ba3288..d1972bd 100644
--- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/PutFile.java
+++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/PutFile.java
@@ -16,27 +16,10 @@
  */
 package org.apache.nifi.processors.standard;
 
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.attribute.PosixFileAttributeView;
-import java.nio.file.attribute.PosixFilePermissions;
-import java.nio.file.attribute.UserPrincipalLookupService;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import java.util.regex.Pattern;
-
 import org.apache.nifi.annotation.behavior.InputRequirement;
 import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
 import org.apache.nifi.annotation.behavior.ReadsAttribute;
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.behavior.SupportsBatching;
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
 import org.apache.nifi.annotation.documentation.SeeAlso;
@@ -54,12 +37,31 @@ import org.apache.nifi.processor.exception.ProcessException;
 import org.apache.nifi.processor.util.StandardValidators;
 import org.apache.nifi.util.StopWatch;
 
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.PosixFileAttributeView;
+import java.nio.file.attribute.PosixFilePermissions;
+import java.nio.file.attribute.UserPrincipalLookupService;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
+
 @SupportsBatching
 @InputRequirement(Requirement.INPUT_REQUIRED)
-@Tags({"put", "local", "copy", "archive", "files", "filesystem"})
+@Tags({"put", "local", "copy", "archive", "files", "filesystem", "restricted"})
 @CapabilityDescription("Writes the contents of a FlowFile to the local file system")
 @SeeAlso({FetchFile.class, GetFile.class})
 @ReadsAttribute(attribute = "filename", description = "The filename to use when writing the FlowFile to disk.")
+@Restricted("Provides operator the ability to write to any file that NiFi has access to.")
 public class PutFile extends AbstractProcessor {
 
     public static final String REPLACE_RESOLUTION = "replace";

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/TailFile.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/TailFile.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/TailFile.java
index a171977..3b71609 100644
--- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/TailFile.java
+++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/TailFile.java
@@ -16,39 +16,11 @@
  */
 package org.apache.nifi.processors.standard;
 
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.file.DirectoryStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardOpenOption;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.regex.Pattern;
-import java.util.zip.CRC32;
-import java.util.zip.CheckedInputStream;
-import java.util.zip.Checksum;
-
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.annotation.behavior.InputRequirement;
 import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.behavior.Stateful;
 import org.apache.nifi.annotation.behavior.TriggerSerially;
 import org.apache.nifi.annotation.behavior.WritesAttribute;
@@ -76,10 +48,39 @@ import org.apache.nifi.stream.io.ByteArrayOutputStream;
 import org.apache.nifi.stream.io.NullOutputStream;
 import org.apache.nifi.stream.io.StreamUtils;
 
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.regex.Pattern;
+import java.util.zip.CRC32;
+import java.util.zip.CheckedInputStream;
+import java.util.zip.Checksum;
+
 // note: it is important that this Processor is not marked as @SupportsBatching because the session commits must complete before persisting state locally; otherwise, data loss may occur
 @TriggerSerially
 @InputRequirement(Requirement.INPUT_FORBIDDEN)
-@Tags({"tail", "file", "log", "text", "source"})
+@Tags({"tail", "file", "log", "text", "source", "restricted"})
 @CapabilityDescription("\"Tails\" a file, or a list of files, ingesting data from the file as it is written to the file. The file is expected to be textual. Data is ingested only when a "
         + "new line is encountered (carriage return or new-line character or combination). If the file to tail is periodically \"rolled over\", as is generally the case "
         + "with log files, an optional Rolling Filename Pattern can be used to retrieve data from files that have rolled over, even if the rollover occurred while NiFi "
@@ -91,6 +92,7 @@ import org.apache.nifi.stream.io.StreamUtils;
 @WritesAttributes({
     @WritesAttribute(attribute = "tailfile.original.path", description = "Path of the original file the flow file comes from.")
     })
+@Restricted("Provides operator the ability to read from any file that NiFi has access to.")
 public class TailFile extends AbstractProcessor {
 
     static final String MAP_PREFIX = "file.";


[2/3] nifi git commit: NIFI-3050: Implemented access control logic for restricted components.

Posted by al...@apache.org.
http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
index 52af285..7aa8321 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
@@ -23,6 +23,7 @@ import org.apache.nifi.authorization.resource.DataAuthorizable;
 import org.apache.nifi.authorization.resource.DataTransferAuthorizable;
 import org.apache.nifi.authorization.resource.ResourceFactory;
 import org.apache.nifi.authorization.resource.ResourceType;
+import org.apache.nifi.authorization.resource.RestrictedComponentsAuthorizable;
 import org.apache.nifi.authorization.resource.TenantAuthorizable;
 import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.components.PropertyDescriptor;
@@ -62,6 +63,8 @@ import java.util.Set;
 class StandardAuthorizableLookup implements AuthorizableLookup {
 
     private static final TenantAuthorizable TENANT_AUTHORIZABLE = new TenantAuthorizable();
+    private static final Authorizable RESTRICTED_COMPONENTS_AUTHORIZABLE = new RestrictedComponentsAuthorizable();
+
     private static final Authorizable POLICIES_AUTHORIZABLE = new Authorizable() {
         @Override
         public Authorizable getParentAuthorizable() {
@@ -134,15 +137,20 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
     }
 
     @Override
-    public ControllerServiceReferencingComponentAuthorizable getProcessor(final String id) {
+    public ConfigurableComponentAuthorizable getProcessor(final String id) {
         final ProcessorNode processorNode = processorDAO.getProcessor(id);
-        return new ControllerServiceReferencingComponentAuthorizable() {
+        return new ConfigurableComponentAuthorizable() {
             @Override
             public Authorizable getAuthorizable() {
                 return processorNode;
             }
 
             @Override
+            public boolean isRestricted() {
+                return processorNode.isRestricted();
+            }
+
+            @Override
             public String getValue(PropertyDescriptor propertyDescriptor) {
                 return processorNode.getProperty(propertyDescriptor);
             }
@@ -155,16 +163,21 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
     }
 
     @Override
-    public ControllerServiceReferencingComponentAuthorizable getProcessorByType(String type) {
+    public ConfigurableComponentAuthorizable getProcessorByType(String type) {
         try {
             final ProcessorNode processorNode = controllerFacade.createTemporaryProcessor(type);
-            return new ControllerServiceReferencingComponentAuthorizable() {
+            return new ConfigurableComponentAuthorizable() {
                 @Override
                 public Authorizable getAuthorizable() {
                     return processorNode;
                 }
 
                 @Override
+                public boolean isRestricted() {
+                    return processorNode.isRestricted();
+                }
+
+                @Override
                 public String getValue(PropertyDescriptor propertyDescriptor) {
                     return processorNode.getProperty(propertyDescriptor);
                 }
@@ -328,15 +341,20 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
     }
 
     @Override
-    public ControllerServiceReferencingComponentAuthorizable getControllerService(final String id) {
+    public ConfigurableComponentAuthorizable getControllerService(final String id) {
         final ControllerServiceNode controllerService = controllerServiceDAO.getControllerService(id);
-        return new ControllerServiceReferencingComponentAuthorizable() {
+        return new ConfigurableComponentAuthorizable() {
             @Override
             public Authorizable getAuthorizable() {
                 return controllerService;
             }
 
             @Override
+            public boolean isRestricted() {
+                return controllerService.isRestricted();
+            }
+
+            @Override
             public String getValue(PropertyDescriptor propertyDescriptor) {
                 return controllerService.getProperty(propertyDescriptor);
             }
@@ -349,16 +367,21 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
     }
 
     @Override
-    public ControllerServiceReferencingComponentAuthorizable getControllerServiceByType(String type) {
+    public ConfigurableComponentAuthorizable getControllerServiceByType(String type) {
         try {
             final ControllerServiceNode controllerService = controllerFacade.createTemporaryControllerService(type);
-            return new ControllerServiceReferencingComponentAuthorizable() {
+            return new ConfigurableComponentAuthorizable() {
                 @Override
                 public Authorizable getAuthorizable() {
                     return controllerService;
                 }
 
                 @Override
+                public boolean isRestricted() {
+                    return controllerService.isRestricted();
+                }
+
+                @Override
                 public String getValue(PropertyDescriptor propertyDescriptor) {
                     return controllerService.getProperty(propertyDescriptor);
                 }
@@ -417,15 +440,20 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
     }
 
     @Override
-    public ControllerServiceReferencingComponentAuthorizable getReportingTask(final String id) {
+    public ConfigurableComponentAuthorizable getReportingTask(final String id) {
         final ReportingTaskNode reportingTaskNode = reportingTaskDAO.getReportingTask(id);
-        return new ControllerServiceReferencingComponentAuthorizable() {
+        return new ConfigurableComponentAuthorizable() {
             @Override
             public Authorizable getAuthorizable() {
                 return reportingTaskNode;
             }
 
             @Override
+            public boolean isRestricted() {
+                return reportingTaskNode.isRestricted();
+            }
+
+            @Override
             public String getValue(PropertyDescriptor propertyDescriptor) {
                 return reportingTaskNode.getProperty(propertyDescriptor);
             }
@@ -438,16 +466,21 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
     }
 
     @Override
-    public ControllerServiceReferencingComponentAuthorizable getReportingTaskByType(String type) {
+    public ConfigurableComponentAuthorizable getReportingTaskByType(String type) {
         try {
             final ReportingTaskNode reportingTask = controllerFacade.createTemporaryReportingTask(type);
-            return new ControllerServiceReferencingComponentAuthorizable() {
+            return new ConfigurableComponentAuthorizable() {
                 @Override
                 public Authorizable getAuthorizable() {
                     return reportingTask;
                 }
 
                 @Override
+                public boolean isRestricted() {
+                    return reportingTask.isRestricted();
+                }
+
+                @Override
                 public String getValue(PropertyDescriptor propertyDescriptor) {
                     return reportingTask.getProperty(propertyDescriptor);
                 }
@@ -603,17 +636,7 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
                 authorizable = getController();
                 break;
             case Counters:
-                authorizable = new Authorizable() {
-                    @Override
-                    public Authorizable getParentAuthorizable() {
-                        return null;
-                    }
-
-                    @Override
-                    public Resource getResource() {
-                        return ResourceFactory.getCountersResource();
-                    }
-                };
+                authorizable = getCounters();
                 break;
             case Flow:
                 authorizable = new Authorizable() {
@@ -629,17 +652,7 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
                 };
                 break;
             case Provenance:
-                authorizable = new Authorizable() {
-                    @Override
-                    public Authorizable getParentAuthorizable() {
-                        return null;
-                    }
-
-                    @Override
-                    public Resource getResource() {
-                        return ResourceFactory.getProvenanceResource();
-                    }
-                };
+                authorizable = getProvenance();
                 break;
             case Proxy:
                 authorizable = new Authorizable() {
@@ -655,7 +668,7 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
                 };
                 break;
             case Policy:
-                authorizable = POLICIES_AUTHORIZABLE;
+                authorizable = getPolicies();
                 break;
             case Resource:
                 authorizable = new Authorizable() {
@@ -671,7 +684,6 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
                 };
                 break;
             case SiteToSite:
-                // TODO - new site-to-site and port specific site-to-site
                 authorizable = new Authorizable() {
                     @Override
                     public Authorizable getParentAuthorizable() {
@@ -685,21 +697,14 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
                 };
                 break;
             case System:
-                authorizable = new Authorizable() {
-                    @Override
-                    public Authorizable getParentAuthorizable() {
-                        return null;
-                    }
-
-                    @Override
-                    public Resource getResource() {
-                        return ResourceFactory.getSystemResource();
-                    }
-                };
+                authorizable = getSystem();
                 break;
             case Tenant:
                 authorizable = getTenant();
                 break;
+            case RestrictedComponents:
+                authorizable = getRestrictedComponents();
+                break;
         }
 
         if (authorizable == null) {
@@ -721,6 +726,11 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
     }
 
     @Override
+    public Authorizable getRestrictedComponents() {
+        return RESTRICTED_COMPONENTS_AUTHORIZABLE;
+    }
+
+    @Override
     public Authorizable getSystem() {
         return SYSTEM_AUTHORIZABLE;
     }

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
index 53c0fe6..67f768a 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
@@ -2958,6 +2958,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
         entity.setControllerPermissions(dtoFactory.createPermissionsDto(authorizableLookup.getController()));
         entity.setPoliciesPermissions(dtoFactory.createPermissionsDto(authorizableLookup.getPolicies()));
         entity.setSystemPermissions(dtoFactory.createPermissionsDto(authorizableLookup.getSystem()));
+        entity.setRestrictedComponentsPermissions(dtoFactory.createPermissionsDto(authorizableLookup.getRestrictedComponents()));
         return entity;
     }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebConfigurationContext.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebConfigurationContext.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebConfigurationContext.java
index fb38ce9..177e557 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebConfigurationContext.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebConfigurationContext.java
@@ -31,7 +31,7 @@ import org.apache.nifi.authorization.AuthorizationResult;
 import org.apache.nifi.authorization.AuthorizationResult.Result;
 import org.apache.nifi.authorization.AuthorizeControllerServiceReference;
 import org.apache.nifi.authorization.Authorizer;
-import org.apache.nifi.authorization.ControllerServiceReferencingComponentAuthorizable;
+import org.apache.nifi.authorization.ConfigurableComponentAuthorizable;
 import org.apache.nifi.authorization.RequestAction;
 import org.apache.nifi.authorization.UserContextKeys;
 import org.apache.nifi.authorization.resource.Authorizable;
@@ -397,7 +397,7 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration
             // authorize access
             serviceFacade.authorizeAccess(lookup -> {
                 // authorize the processor
-                final ControllerServiceReferencingComponentAuthorizable authorizable = lookup.getProcessor(id);
+                final ConfigurableComponentAuthorizable authorizable = lookup.getProcessor(id);
                 authorizable.getAuthorizable().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
 
                 // authorize any referenced service
@@ -588,7 +588,7 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration
             // authorize access
             serviceFacade.authorizeAccess(lookup -> {
                 // authorize the controller service
-                final ControllerServiceReferencingComponentAuthorizable authorizable = lookup.getControllerService(id);
+                final ConfigurableComponentAuthorizable authorizable = lookup.getControllerService(id);
                 authorizable.getAuthorizable().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
 
                 // authorize any referenced service
@@ -753,7 +753,7 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration
             // authorize access
             serviceFacade.authorizeAccess(lookup -> {
                 // authorize the reporting task
-                final ControllerServiceReferencingComponentAuthorizable authorizable = lookup.getReportingTask(id);
+                final ConfigurableComponentAuthorizable authorizable = lookup.getReportingTask(id);
                 authorizable.getAuthorizable().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
 
                 // authorize any referenced service

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
index 09abe53..8f33ba6 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
@@ -30,7 +30,7 @@ import org.apache.nifi.authorization.AuthorizationResult;
 import org.apache.nifi.authorization.AuthorizationResult.Result;
 import org.apache.nifi.authorization.AuthorizeControllerServiceReference;
 import org.apache.nifi.authorization.Authorizer;
-import org.apache.nifi.authorization.ControllerServiceReferencingComponentAuthorizable;
+import org.apache.nifi.authorization.ConfigurableComponentAuthorizable;
 import org.apache.nifi.authorization.RequestAction;
 import org.apache.nifi.authorization.UserContextKeys;
 import org.apache.nifi.authorization.resource.ResourceFactory;
@@ -283,8 +283,12 @@ public class ControllerResource extends ApplicationResource {
                 lookup -> {
                     authorizeController(RequestAction.WRITE);
 
+                    final ConfigurableComponentAuthorizable authorizable = lookup.getProcessorByType(requestReportingTask.getType());
+                    if (authorizable.isRestricted()) {
+                        lookup.getRestrictedComponents().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
+                    }
+
                     if (requestReportingTask.getProperties() != null) {
-                        final ControllerServiceReferencingComponentAuthorizable authorizable = lookup.getReportingTaskByType(requestReportingTask.getType());
                         AuthorizeControllerServiceReference.authorizeControllerServiceReferences(requestReportingTask.getProperties(), authorizable, authorizer, lookup);
                     }
                 },
@@ -376,8 +380,12 @@ public class ControllerResource extends ApplicationResource {
                 lookup -> {
                     authorizeController(RequestAction.WRITE);
 
+                    final ConfigurableComponentAuthorizable authorizable = lookup.getProcessorByType(requestControllerService.getType());
+                    if (authorizable.isRestricted()) {
+                        lookup.getRestrictedComponents().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
+                    }
+
                     if (requestControllerService.getProperties() != null) {
-                        final ControllerServiceReferencingComponentAuthorizable authorizable = lookup.getControllerServiceByType(requestControllerService.getType());
                         AuthorizeControllerServiceReference.authorizeControllerServiceReferences(requestControllerService.getProperties(), authorizable, authorizer, lookup);
                     }
                 },

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerServiceResource.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerServiceResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerServiceResource.java
index 9b3805a..47a8189 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerServiceResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerServiceResource.java
@@ -25,7 +25,7 @@ import com.wordnik.swagger.annotations.Authorization;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.authorization.AuthorizeControllerServiceReference;
 import org.apache.nifi.authorization.Authorizer;
-import org.apache.nifi.authorization.ControllerServiceReferencingComponentAuthorizable;
+import org.apache.nifi.authorization.ConfigurableComponentAuthorizable;
 import org.apache.nifi.authorization.RequestAction;
 import org.apache.nifi.authorization.resource.Authorizable;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
@@ -621,7 +621,7 @@ public class ControllerServiceResource extends ApplicationResource {
                 requestRevision,
                 lookup -> {
                     // authorize the service
-                    final ControllerServiceReferencingComponentAuthorizable authorizable = lookup.getControllerService(id);
+                    final ConfigurableComponentAuthorizable authorizable = lookup.getControllerService(id);
                     authorizable.getAuthorizable().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
 
                     // authorize any referenced services

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java
index 527364c..c1ea58c 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java
@@ -28,7 +28,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.authorization.AuthorizableLookup;
 import org.apache.nifi.authorization.AuthorizeControllerServiceReference;
 import org.apache.nifi.authorization.Authorizer;
-import org.apache.nifi.authorization.ControllerServiceReferencingComponentAuthorizable;
+import org.apache.nifi.authorization.ConfigurableComponentAuthorizable;
 import org.apache.nifi.authorization.ProcessGroupAuthorizable;
 import org.apache.nifi.authorization.RequestAction;
 import org.apache.nifi.authorization.resource.Authorizable;
@@ -615,12 +615,18 @@ public class ProcessGroupResource extends ApplicationResource {
                 serviceFacade,
                 requestProcessorEntity,
                 lookup -> {
+                    final NiFiUser user = NiFiUserUtils.getNiFiUser();
+
                     final Authorizable processGroup = lookup.getProcessGroup(groupId).getAuthorizable();
-                    processGroup.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
+                    processGroup.authorize(authorizer, RequestAction.WRITE, user);
+
+                    final ConfigurableComponentAuthorizable authorizable = lookup.getProcessorByType(requestProcessor.getType());
+                    if (authorizable.isRestricted()) {
+                        lookup.getRestrictedComponents().authorize(authorizer, RequestAction.WRITE, user);
+                    }
 
                     final ProcessorConfigDTO config = requestProcessor.getConfig();
                     if (config != null && config.getProperties() != null) {
-                        final ControllerServiceReferencingComponentAuthorizable authorizable = lookup.getProcessorByType(requestProcessor.getType());
                         AuthorizeControllerServiceReference.authorizeControllerServiceReferences(config.getProperties(), authorizable, authorizer, lookup);
                     }
                 },
@@ -2129,11 +2135,17 @@ public class ProcessGroupResource extends ApplicationResource {
                 serviceFacade,
                 requestControllerServiceEntity,
                 lookup -> {
+                    final NiFiUser user = NiFiUserUtils.getNiFiUser();
+
                     final Authorizable processGroup = lookup.getProcessGroup(groupId).getAuthorizable();
-                    processGroup.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
+                    processGroup.authorize(authorizer, RequestAction.WRITE, user);
+
+                    final ConfigurableComponentAuthorizable authorizable = lookup.getProcessorByType(requestControllerService.getType());
+                    if (authorizable.isRestricted()) {
+                        lookup.getRestrictedComponents().authorize(authorizer, RequestAction.WRITE, user);
+                    }
 
                     if (requestControllerService.getProperties() != null) {
-                        final ControllerServiceReferencingComponentAuthorizable authorizable = lookup.getControllerServiceByType(requestControllerService.getType());
                         AuthorizeControllerServiceReference.authorizeControllerServiceReferences(requestControllerService.getProperties(), authorizable, authorizer, lookup);
                     }
                 },

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessorResource.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessorResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessorResource.java
index cc16d26..fcdb99f 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessorResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessorResource.java
@@ -25,7 +25,7 @@ import com.wordnik.swagger.annotations.Authorization;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.authorization.AuthorizeControllerServiceReference;
 import org.apache.nifi.authorization.Authorizer;
-import org.apache.nifi.authorization.ControllerServiceReferencingComponentAuthorizable;
+import org.apache.nifi.authorization.ConfigurableComponentAuthorizable;
 import org.apache.nifi.authorization.RequestAction;
 import org.apache.nifi.authorization.resource.Authorizable;
 import org.apache.nifi.authorization.user.NiFiUser;
@@ -448,7 +448,7 @@ public class ProcessorResource extends ApplicationResource {
                 lookup -> {
                     final NiFiUser user = NiFiUserUtils.getNiFiUser();
 
-                    final ControllerServiceReferencingComponentAuthorizable authorizable = lookup.getProcessor(id);
+                    final ConfigurableComponentAuthorizable authorizable = lookup.getProcessor(id);
                     authorizable.getAuthorizable().authorize(authorizer, RequestAction.WRITE, user);
 
                     final ProcessorConfigDTO config = requestProcessorDTO.getConfig();

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ReportingTaskResource.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ReportingTaskResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ReportingTaskResource.java
index 4d23804..57bc51d 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ReportingTaskResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ReportingTaskResource.java
@@ -25,7 +25,7 @@ import com.wordnik.swagger.annotations.Authorization;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.authorization.AuthorizeControllerServiceReference;
 import org.apache.nifi.authorization.Authorizer;
-import org.apache.nifi.authorization.ControllerServiceReferencingComponentAuthorizable;
+import org.apache.nifi.authorization.ConfigurableComponentAuthorizable;
 import org.apache.nifi.authorization.RequestAction;
 import org.apache.nifi.authorization.resource.Authorizable;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
@@ -425,7 +425,7 @@ public class ReportingTaskResource extends ApplicationResource {
                 requestRevision,
                 lookup -> {
                     // authorize reporting task
-                    final ControllerServiceReferencingComponentAuthorizable authorizable = lookup.getReportingTask(id);
+                    final ConfigurableComponentAuthorizable authorizable = lookup.getReportingTask(id);
                     authorizable.getAuthorizable().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
 
                     // authorize any referenced services

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
index 3383632..3f48128 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
@@ -31,6 +31,7 @@ import org.apache.nifi.action.details.FlowChangeMoveDetails;
 import org.apache.nifi.action.details.FlowChangePurgeDetails;
 import org.apache.nifi.action.details.MoveDetails;
 import org.apache.nifi.action.details.PurgeDetails;
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.behavior.Stateful;
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
 import org.apache.nifi.annotation.documentation.Tags;
@@ -1239,6 +1240,7 @@ public final class DtoFactory {
         dto.setAnnotationData(reportingTaskNode.getAnnotationData());
         dto.setComments(reportingTaskNode.getComments());
         dto.setPersistsState(reportingTaskNode.getReportingTask().getClass().isAnnotationPresent(Stateful.class));
+        dto.setRestricted(reportingTaskNode.isRestricted());
 
         final Map<String, String> defaultSchedulingPeriod = new HashMap<>();
         defaultSchedulingPeriod.put(SchedulingStrategy.TIMER_DRIVEN.name(), SchedulingStrategy.TIMER_DRIVEN.getDefaultSchedulingPeriod());
@@ -1308,6 +1310,7 @@ public final class DtoFactory {
         dto.setAnnotationData(controllerServiceNode.getAnnotationData());
         dto.setComments(controllerServiceNode.getComments());
         dto.setPersistsState(controllerServiceNode.getControllerServiceImplementation().getClass().isAnnotationPresent(Stateful.class));
+        dto.setRestricted(controllerServiceNode.isRestricted());
 
         // sort a copy of the properties
         final Map<PropertyDescriptor, String> sortedProperties = new TreeMap<>(new Comparator<PropertyDescriptor>() {
@@ -2011,6 +2014,11 @@ public final class DtoFactory {
         return dto;
     }
 
+    private String getUsageRestriction(final Class<?> cls) {
+        final Restricted restriction = cls.getAnnotation(Restricted.class);
+        return restriction == null ? null : restriction.value();
+    }
+
     /**
      * Gets the capability description from the specified class.
      */
@@ -2050,6 +2058,7 @@ public final class DtoFactory {
             final DocumentedTypeDTO type = new DocumentedTypeDTO();
             type.setType(cls.getName());
             type.setDescription(getCapabilityDescription(cls));
+            type.setUsageRestriction(getUsageRestriction(cls));
             type.setTags(getTags(cls));
             types.add(type);
         }
@@ -2075,6 +2084,7 @@ public final class DtoFactory {
         dto.setParentGroupId(node.getProcessGroup().getIdentifier());
         dto.setInputRequirement(node.getInputRequirement().name());
         dto.setPersistsState(node.getProcessor().getClass().isAnnotationPresent(Stateful.class));
+        dto.setRestricted(node.isRestricted());
 
         dto.setType(node.getCanonicalClassName());
         dto.setName(node.getName());

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
index 41eaae3..30fcbd7 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
@@ -788,6 +788,7 @@ public class ControllerFacade implements Authorizable {
         final List<Resource> resources = new ArrayList<>();
         resources.add(ResourceFactory.getFlowResource());
         resources.add(ResourceFactory.getSystemResource());
+        resources.add(ResourceFactory.getRestrictedComponentsResource());
         resources.add(ResourceFactory.getControllerResource());
         resources.add(ResourceFactory.getCountersResource());
         resources.add(ResourceFactory.getProvenanceResource());

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/AccessControlHelper.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/AccessControlHelper.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/AccessControlHelper.java
index 6bd0b36..d22f418 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/AccessControlHelper.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/AccessControlHelper.java
@@ -43,6 +43,7 @@ public class AccessControlHelper {
     private NiFiTestUser writeUser;
     private NiFiTestUser readWriteUser;
     private NiFiTestUser noneUser;
+    private NiFiTestUser privilegedUser;
 
     private static final String CONTEXT_PATH = "/nifi-api";
 
@@ -78,6 +79,7 @@ public class AccessControlHelper {
         writeUser = new NiFiTestUser(server.getClient(), NiFiTestAuthorizer.WRITE_USER_DN);
         readWriteUser = new NiFiTestUser(server.getClient(), NiFiTestAuthorizer.READ_WRITE_USER_DN);
         noneUser = new NiFiTestUser(server.getClient(), NiFiTestAuthorizer.NONE_USER_DN);
+        privilegedUser = new NiFiTestUser(server.getClient(), NiFiTestAuthorizer.PRIVILEGED_USER_DN);
 
         // populate the initial data flow
         NiFiWebApiTest.populateFlow(server.getClient(), baseUrl, readWriteUser, READ_WRITE_CLIENT_ID);
@@ -99,6 +101,10 @@ public class AccessControlHelper {
         return noneUser;
     }
 
+    public NiFiTestUser getPrivilegedUser() {
+        return privilegedUser;
+    }
+
     public void testGenericGetUri(final String uri) throws Exception {
         ClientResponse response;
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITProcessorAccessControl.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/ITProcessorAccessControl.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITProcessorAccessControl.java
index 37567c4..02817fc 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITProcessorAccessControl.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ITProcessorAccessControl.java
@@ -19,6 +19,7 @@ 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.integration.util.RestrictedProcessor;
 import org.apache.nifi.integration.util.SourceTestProcessor;
 import org.apache.nifi.web.api.dto.ProcessorDTO;
 import org.apache.nifi.web.api.dto.RevisionDTO;
@@ -399,6 +400,43 @@ public class ITProcessorAccessControl {
         verifyDelete(helper.getNoneUser(), NONE_CLIENT_ID, 403);
     }
 
+    /**
+     * Tests attempt to create a restricted processor.
+     *
+     * @throws Exception if there is an error creating this processor
+     */
+    @Test
+    public void testCreateRestrictedProcessor() throws Exception {
+        String url = helper.getBaseUrl() + "/process-groups/root/processors";
+
+        // create the processor
+        ProcessorDTO processor = new ProcessorDTO();
+        processor.setName("restricted");
+        processor.setType(RestrictedProcessor.class.getName());
+
+        // create the revision
+        final RevisionDTO revision = new RevisionDTO();
+        revision.setClientId(READ_WRITE_CLIENT_ID);
+        revision.setVersion(0L);
+
+        // create the entity body
+        ProcessorEntity entity = new ProcessorEntity();
+        entity.setRevision(revision);
+        entity.setComponent(processor);
+
+        // perform the request as a user with read/write but no restricted access
+        ClientResponse response = helper.getReadWriteUser().testPost(url, entity);
+
+        // ensure the request is successful
+        assertEquals(403, response.getStatus());
+
+        // perform the request as a user with read/write and restricted access
+        response = helper.getPrivilegedUser().testPost(url, entity);
+
+        // ensure the request is successful
+        assertEquals(201, response.getStatus());
+    }
+
     private ProcessorEntity getRandomProcessor(final NiFiTestUser user) throws Exception {
         final String url = helper.getBaseUrl() + "/flow/process-groups/root";
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/util/NiFiTestAuthorizer.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/util/NiFiTestAuthorizer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/util/NiFiTestAuthorizer.java
index f5d70cf..de55b83 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/util/NiFiTestAuthorizer.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/util/NiFiTestAuthorizer.java
@@ -39,6 +39,7 @@ public class NiFiTestAuthorizer implements Authorizer {
     public static final String READ_USER_DN = "read@nifi";
     public static final String WRITE_USER_DN = "write@nifi";
     public static final String READ_WRITE_USER_DN = "readwrite@nifi";
+    public static final String PRIVILEGED_USER_DN = "privileged@nifi";
 
     public static final String TOKEN_USER = "user@nifi";
 
@@ -78,15 +79,24 @@ public class NiFiTestAuthorizer implements Authorizer {
             return AuthorizationResult.approved();
         }
 
+        // restricted component access
+        if (ResourceFactory.getRestrictedComponentsResource().getIdentifier().equals(request.getResource().getIdentifier())) {
+            if (PRIVILEGED_USER_DN.equals(request.getIdentity())) {
+                return AuthorizationResult.approved();
+            } else {
+                return AuthorizationResult.denied();
+            }
+        }
+
         // read access
-        if (READ_USER_DN.equals(request.getIdentity()) || READ_WRITE_USER_DN.equals(request.getIdentity())) {
+        if (READ_USER_DN.equals(request.getIdentity()) || READ_WRITE_USER_DN.equals(request.getIdentity()) || PRIVILEGED_USER_DN.equals(request.getIdentity())) {
             if (RequestAction.READ.equals(request.getAction())) {
                 return AuthorizationResult.approved();
             }
         }
 
         // write access
-        if (WRITE_USER_DN.equals(request.getIdentity()) || READ_WRITE_USER_DN.equals(request.getIdentity())) {
+        if (WRITE_USER_DN.equals(request.getIdentity()) || READ_WRITE_USER_DN.equals(request.getIdentity()) || PRIVILEGED_USER_DN.equals(request.getIdentity())) {
             if (RequestAction.WRITE.equals(request.getAction())) {
                 return AuthorizationResult.approved();
             }

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/util/RestrictedProcessor.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/util/RestrictedProcessor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/util/RestrictedProcessor.java
new file mode 100644
index 0000000..4da4b5a
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/util/RestrictedProcessor.java
@@ -0,0 +1,51 @@
+/*
+ * 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.util;
+
+import org.apache.nifi.annotation.behavior.Restricted;
+import org.apache.nifi.processor.AbstractSessionFactoryProcessor;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.ProcessSessionFactory;
+import org.apache.nifi.processor.ProcessorInitializationContext;
+import org.apache.nifi.processor.Relationship;
+import org.apache.nifi.processor.exception.ProcessException;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@Restricted("")
+public class RestrictedProcessor extends AbstractSessionFactoryProcessor {
+
+    public RestrictedProcessor() {
+    }
+
+    @Override
+    public Set<Relationship> getRelationships() {
+        final Set<Relationship> rels = new HashSet<>();
+        rels.add(new Relationship.Builder().name("success").build());
+        return rels;
+    }
+
+    @Override
+    public void onTrigger(final ProcessContext context, final ProcessSessionFactory sessionFactory) throws ProcessException {
+    }
+
+    @Override
+    protected void init(final ProcessorInitializationContext context) {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css
index 0466df5..cdd8318 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css
@@ -427,7 +427,13 @@ div.button {
     cursor: pointer;
 }
 
-div.button:hover {
+div.button.disabled-button {
+    color: #a8a8a8 !important;
+    cursor: not-allowed;
+    opacity: 0.7;
+}
+
+div.button:hover:not(.disabled-button) {
     background-color: #004849;
 }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/graph.css
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/graph.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/graph.css
index e965bf2..bc198a9 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/graph.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/graph.css
@@ -175,6 +175,18 @@ text.processor-icon {
     font-size: 30px;
 }
 
+circle.restricted-background {
+    visibility: hidden;
+    fill: rgba(255, 255, 255, 0.90);
+}
+
+text.restricted {
+    visibility: hidden;
+    font-family: FontAwesome;
+    font-size: 12px;
+    fill: #ba554a;
+}
+
 text.run-status-icon {
     font-size: 13px;
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/new-processor-dialog.css
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/new-processor-dialog.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/new-processor-dialog.css
index 111550c..29a3232 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/new-processor-dialog.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/new-processor-dialog.css
@@ -86,4 +86,12 @@
 
 #processor-type-filter {
     width: 200px;
+}
+
+/*
+    Restricted
+*/
+
+div.view-usage-restriction {
+    color: #ba554a !important;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/policy-management.css
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/policy-management.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/policy-management.css
index a1a5f89..8b90b8d 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/policy-management.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/policy-management.css
@@ -89,7 +89,7 @@ div.policy-controls {
 
 #policy-type-list {
     float: left;
-    width: 190px;
+    width: 225px;
     margin-right: 3px;
     border-left: 1px solid transparent;
     border-right: 1px solid transparent;

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/modal/jquery.modal.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/modal/jquery.modal.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/modal/jquery.modal.js
index 82f8bf6..03cca96 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/modal/jquery.modal.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/modal/jquery.modal.js
@@ -36,6 +36,7 @@
  *              hover: '#004849',
  *              text: '#ffffff'
  *          },
+ *          disabled: isDisabledFunction,
  *      handler: {
  *          click: cancelHandler
  *      }
@@ -46,6 +47,7 @@
  *              hover: '#C7D2D7',
  *              text: '#004849'
  *          },
+ *          disabled: isDisabledFunction,
  *      handler: {
  *          click: applyHandler
  *      }
@@ -101,27 +103,54 @@
     var addButtons = function (dialog, buttonModel) {
         if (isDefinedAndNotNull(buttonModel)) {
             var buttonWrapper = $('<div class="dialog-buttons"></div>');
-            var button;
             $.each(buttonModel, function (i, buttonConfig) {
-                var clazz = isDefinedAndNotNull(buttonConfig.clazz) ? buttonConfig.clazz : '';
-                if (buttonConfig.color) {
-                    button = $('<div class="button ' + clazz + '" style="color:' + buttonConfig.color.text + '; background:' + buttonConfig.color.base + ';"><span>' + buttonConfig.buttonText + '</span></div>');
-                    button.hover(function () {
-                        $(this).css("background-color", buttonConfig.color.hover);
-                    }, function () {
-                        $(this).css("background-color", buttonConfig.color.base);
+                var isDisabled = function () {
+                    return typeof buttonConfig.disabled === 'function' && buttonConfig.disabled.call() === true;
+                };
+
+                // create the button
+                var button = $('<div class="button"></div>').append($('<span></span>').text(buttonConfig.buttonText));
+
+                // add the class if specified
+                if (isDefinedAndNotNull(buttonConfig.clazz)) {
+                    button.addClass(buttonConfig.clazz);
+                }
+
+                // set the color if specified
+                if (isDefinedAndNotNull(buttonConfig.color)) {
+                    button.css({
+                        'background': buttonConfig.color.base,
+                        'color': buttonConfig.color.text
                     });
-                } else {
-                    button = $('<div class="button ' + clazz + '"><span>' + buttonConfig.buttonText + '</span></div>');
                 }
-                button.click(function () {
-                    var handler = $(this).data('handler');
-                    if (isDefinedAndNotNull(handler) && typeof handler.click === 'function') {
-                        handler.click.call(dialog);
+
+                // check if the button should be disabled
+                if (isDisabled()) {
+                    button.addClass('disabled-button');
+                } else {
+                    // enable custom hover if specified
+                    if (isDefinedAndNotNull(buttonConfig.color)) {
+                        button.hover(function () {
+                            $(this).css("background-color", buttonConfig.color.hover);
+                        }, function () {
+                            $(this).css("background-color", buttonConfig.color.base);
+                        });
                     }
-                }).data('handler', buttonConfig.handler).appendTo(buttonWrapper);
+
+                    button.click(function () {
+                        var handler = $(this).data('handler');
+                        if (isDefinedAndNotNull(handler) && typeof handler.click === 'function') {
+                            handler.click.call(dialog);
+                        }
+                    });
+                }
+
+                // add the button to the wrapper
+                button.data('handler', buttonConfig.handler).appendTo(buttonWrapper);
             });
-            buttonWrapper.appendTo(dialog);
+
+            // store the button model to refresh later
+            dialog.append(buttonWrapper).data('buttonModel', buttonModel);
         }
     };
 
@@ -259,6 +288,22 @@
         },
 
         /**
+         * Refreshes the buttons with the existing model.
+         */
+        refreshButtons: function () {
+            return this.each(function () {
+                var dialog = $(this);
+                var buttons = dialog.data('buttonModel');
+
+                // remove the current buttons
+                dialog.children('.dialog-buttons').remove();
+
+                // add the new buttons
+                addButtons(dialog, buttons);
+            });
+        },
+
+        /**
          * Sets the header text of the dialog.
          *
          * @argument {string} text Text to use a as a header

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-processor-component.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-processor-component.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-processor-component.js
index b563b10..c96bab4 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-processor-component.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-processor-component.js
@@ -235,6 +235,15 @@ nf.ng.ProcessorComponent = function (serviceProvider) {
         }).fail(nf.Common.handleAjaxError);
     };
 
+    /**
+     * Whether the specified item is selectable.
+     *
+     * @param item process type
+     */
+    var isSelectable = function (item) {
+        return nf.Common.isBlank(item.usageRestriction) || nf.Common.canAccessRestrictedComponents();
+    };
+
     function ProcessorComponent() {
 
         this.icon = 'icon icon-processor';
@@ -257,7 +266,7 @@ nf.ng.ProcessorComponent = function (serviceProvider) {
                 init: function () {
                     // initialize the processor type table
                     var processorTypesColumns = [
-                        {id: 'type', name: 'Type', field: 'label', sortable: true, resizable: true},
+                        {id: 'type', name: 'Type', field: 'label', formatter: nf.Common.typeFormatter, sortable: true, resizable: true},
                         {id: 'tags', name: 'Tags', field: 'tags', sortable: true, resizable: true}
                     ];
                     var processorTypesOptions = {
@@ -319,9 +328,15 @@ nf.ng.ProcessorComponent = function (serviceProvider) {
                                 $('#processor-type-name').text(processorType.label).ellipsis();
                                 $('#selected-processor-name').text(processorType.label);
                                 $('#selected-processor-type').text(processorType.type);
+
+                                // refresh the buttons based on the current selection
+                                $('#new-processor-dialog').modal('refreshButtons');
                             }
                         }
                     });
+                    processorTypesGrid.onViewportChanged.subscribe(function (e, args) {
+                        nf.Common.cleanUpTooltips($('#processor-types-table'), 'div.view-usage-restriction');
+                    });
 
                     // wire up the dataview to the grid
                     processorTypesData.onRowCountChanged.subscribe(function (e, args) {
@@ -338,7 +353,31 @@ nf.ng.ProcessorComponent = function (serviceProvider) {
                     processorTypesData.syncGridSelection(processorTypesGrid, false);
 
                     // hold onto an instance of the grid
-                    $('#processor-types-table').data('gridInstance', processorTypesGrid);
+                    $('#processor-types-table').data('gridInstance', processorTypesGrid).on('mouseenter', 'div.slick-cell', function (e) {
+                        var usageRestriction = $(this).find('div.view-usage-restriction');
+                        if (usageRestriction.length && !usageRestriction.data('qtip')) {
+                            var rowId = $(this).find('span.row-id').text();
+
+                            // get the status item
+                            var item = processorTypesData.getItemById(rowId);
+
+                            // show the tooltip
+                            if (nf.Common.isDefinedAndNotNull(item.usageRestriction)) {
+                                usageRestriction.qtip($.extend({}, nf.Common.config.tooltipConfig, {
+                                    content: item.usageRestriction,
+                                    position: {
+                                        container: $('#summary'),
+                                        at: 'bottom right',
+                                        my: 'top left',
+                                        adjust: {
+                                            x: 4,
+                                            y: 4
+                                        }
+                                    }
+                                }));
+                            }
+                        }
+                    });
 
                     // load the available processor types, this select is shown in the
                     // new processor dialog when a processor is dragged onto the screen
@@ -362,6 +401,7 @@ nf.ng.ProcessorComponent = function (serviceProvider) {
                                 label: nf.Common.substringAfterLast(type, '.'),
                                 type: type,
                                 description: nf.Common.escapeHtml(documentedType.description),
+                                usageRestriction: nf.Common.escapeHtml(documentedType.usageRestriction),
                                 tags: documentedType.tags.join(', ')
                             });
 
@@ -497,6 +537,7 @@ nf.ng.ProcessorComponent = function (serviceProvider) {
          */
         promptForProcessorType: function (pt) {
             var self = this;
+
             // handles adding the selected processor at the specified point
             var addProcessor = function () {
                 // get the type of processor currently selected
@@ -525,10 +566,12 @@ nf.ng.ProcessorComponent = function (serviceProvider) {
             var gridDoubleClick = function (e, args) {
                 var processorType = grid.getDataItem(args.row);
 
-                $('#selected-processor-name').text(processorType.label);
-                $('#selected-processor-type').text(processorType.type);
+                if (isSelectable(processorType)) {
+                    $('#selected-processor-name').text(processorType.label);
+                    $('#selected-processor-type').text(processorType.type);
 
-                addProcessor();
+                    addProcessor();
+                }
             };
 
             // register a handler for double click events
@@ -542,6 +585,17 @@ nf.ng.ProcessorComponent = function (serviceProvider) {
                     hover: '#004849',
                     text: '#ffffff'
                 },
+                disabled: function () {
+                    var selected = grid.getSelectedRows();
+
+                    if (selected.length > 0) {
+                        // grid configured with multi-select = false
+                        var item = grid.getDataItem(selected[0]);
+                        return isSelectable(item) === false;
+                    } else {
+                        return false;
+                    }
+                },
                 handler: {
                     click: addProcessor
                 }
@@ -576,7 +630,15 @@ nf.ng.ProcessorComponent = function (serviceProvider) {
             $('#processor-type-filter').focus().off('keyup').on('keyup', function (e) {
                 var code = e.keyCode ? e.keyCode : e.which;
                 if (code === $.ui.keyCode.ENTER) {
-                    addProcessor();
+                    var selected = grid.getSelectedRows();
+
+                    if (selected.length > 0) {
+                        // grid configured with multi-select = false
+                        var item = grid.getDataItem(selected[0]);
+                        if (isSelectable(item)) {
+                            addProcessor();
+                        }
+                    }
                 } else {
                     applyFilter();
                 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-services.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-services.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-services.js
index cb88182..9473978 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-services.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-services.js
@@ -40,6 +40,15 @@ nf.ControllerServices = (function () {
     };
 
     /**
+     * Whether the specified item is selectable.
+     *
+     * @param item controller service type
+     */
+    var isSelectable = function (item) {
+        return nf.Common.isBlank(item.usageRestriction) || nf.Common.canAccessRestrictedComponents();
+    };
+
+    /**
      * Get the text out of the filter field. If the filter field doesn't
      * have any text it will contain the text 'filter list' so this method
      * accounts for that.
@@ -254,7 +263,7 @@ nf.ControllerServices = (function () {
     var initNewControllerServiceDialog = function () {
         // initialize the processor type table
         var controllerServiceTypesColumns = [
-            {id: 'type', name: 'Type', field: 'label', sortable: false, resizable: true},
+            {id: 'type', name: 'Type', field: 'label', formatter: nf.Common.typeFormatter, sortable: false, resizable: true},
             {id: 'tags', name: 'Tags', field: 'tags', sortable: false, resizable: true}
         ];
 
@@ -298,9 +307,15 @@ nf.ControllerServices = (function () {
                     $('#controller-service-type-name').text(controllerServiceType.label).ellipsis();
                     $('#selected-controller-service-name').text(controllerServiceType.label);
                     $('#selected-controller-service-type').text(controllerServiceType.type);
+
+                    // refresh the buttons based on the current selection
+                    $('#new-controller-service-dialog').modal('refreshButtons');
                 }
             }
         });
+        controllerServiceTypesGrid.onViewportChanged.subscribe(function (e, args) {
+            nf.Common.cleanUpTooltips($('#controller-service-types-table'), 'div.view-usage-restriction');
+        });
 
         // wire up the dataview to the grid
         controllerServiceTypesData.onRowCountChanged.subscribe(function (e, args) {
@@ -317,7 +332,31 @@ nf.ControllerServices = (function () {
         controllerServiceTypesData.syncGridSelection(controllerServiceTypesGrid, true);
 
         // hold onto an instance of the grid
-        $('#controller-service-types-table').data('gridInstance', controllerServiceTypesGrid);
+        $('#controller-service-types-table').data('gridInstance', controllerServiceTypesGrid).on('mouseenter', 'div.slick-cell', function (e) {
+            var usageRestriction = $(this).find('div.view-usage-restriction');
+            if (usageRestriction.length && !usageRestriction.data('qtip')) {
+                var rowId = $(this).find('span.row-id').text();
+
+                // get the status item
+                var item = controllerServiceTypesData.getItemById(rowId);
+
+                // show the tooltip
+                if (nf.Common.isDefinedAndNotNull(item.usageRestriction)) {
+                    usageRestriction.qtip($.extend({}, nf.Common.config.tooltipConfig, {
+                        content: item.usageRestriction,
+                        position: {
+                            container: $('#summary'),
+                            at: 'bottom right',
+                            my: 'top left',
+                            adjust: {
+                                x: 4,
+                                y: 4
+                            }
+                        }
+                    }));
+                }
+            }
+        });
 
         // load the available controller services
         $.ajax({
@@ -339,6 +378,7 @@ nf.ControllerServices = (function () {
                     label: nf.Common.substringAfterLast(documentedType.type, '.'),
                     type: documentedType.type,
                     description: nf.Common.escapeHtml(documentedType.description),
+                    usageRestriction: nf.Common.escapeHtml(documentedType.usageRestriction),
                     tags: documentedType.tags.join(', ')
                 });
 
@@ -831,11 +871,22 @@ nf.ControllerServices = (function () {
          * @param {jQuery} serviceTable
          */
         promptNewControllerService: function (controllerServicesUri, serviceTable) {
+            // get the grid reference
+            var grid = $('#controller-service-types-table').data('gridInstance');
+
             // update the keyhandler
             $('#controller-service-type-filter').off('keyup').on('keyup', function (e) {
                 var code = e.keyCode ? e.keyCode : e.which;
                 if (code === $.ui.keyCode.ENTER) {
-                    addSelectedControllerService(controllerServicesUri, serviceTable);
+                    var selected = grid.getSelectedRows();
+
+                    if (selected.length > 0) {
+                        // grid configured with multi-select = false
+                        var item = grid.getDataItem(selected[0]);
+                        if (isSelectable(item)) {
+                            addSelectedControllerService(controllerServicesUri, serviceTable);
+                        }
+                    }
                 } else {
                     applyControllerServiceTypeFilter();
                 }
@@ -849,6 +900,17 @@ nf.ControllerServices = (function () {
                     hover: '#004849',
                     text: '#ffffff'
                 },
+                disabled: function () {
+                    var selected = grid.getSelectedRows();
+
+                    if (selected.length > 0) {
+                        // grid configured with multi-select = false
+                        var item = grid.getDataItem(selected[0]);
+                        return isSelectable(item) === false;
+                    } else {
+                        return false;
+                    }
+                },
                 handler: {
                     click: function () {
                         addSelectedControllerService(controllerServicesUri, serviceTable);
@@ -878,7 +940,10 @@ nf.ControllerServices = (function () {
             // update the dbl click handler and subsrcibe
             dblClick = function(e, args) {
                 var controllerServiceType = controllerServiceTypesGrid.getDataItem(args.row);
-                addControllerService(controllerServicesUri, serviceTable, controllerServiceType.type);
+
+                if (isSelectable(controllerServiceType)) {
+                    addControllerService(controllerServicesUri, serviceTable, controllerServiceType.type);
+                }
             };
             controllerServiceTypesGrid.onDblClick.subscribe(dblClick);
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
index 19ea71e..b2f95ba 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
@@ -343,6 +343,7 @@ nf.PolicyManagement = (function () {
                 nf.Common.getPolicyTypeListing('flow'),
                 nf.Common.getPolicyTypeListing('controller'),
                 nf.Common.getPolicyTypeListing('provenance'),
+                nf.Common.getPolicyTypeListing('restricted-components'),
                 nf.Common.getPolicyTypeListing('policies'),
                 nf.Common.getPolicyTypeListing('tenants'),
                 nf.Common.getPolicyTypeListing('site-to-site'),
@@ -364,7 +365,7 @@ nf.PolicyManagement = (function () {
                         $('#controller-policy-target').hide();
 
                         // record the action
-                        if (option.value === 'proxy') {
+                        if (option.value === 'proxy' || option.value === 'restricted-components') {
                             $('#selected-policy-action').text('write');
                         } else {
                             $('#selected-policy-action').text('read');
@@ -1398,7 +1399,7 @@ nf.PolicyManagement = (function () {
 
             if (policyType === 'controller') {
                 $('#selected-policy-action').text($('#controller-policy-target').combo('getSelectedOption').value);
-            } else if (policyType === 'proxy') {
+            } else if (policyType === 'proxy' || policyType === 'restricted-components') {
                 $('#selected-policy-action').text('write');
             } else {
                 $('#selected-policy-action').text('read');

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor.js
index 9a5506a..1a02dae 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor.js
@@ -132,6 +132,24 @@ nf.Processor = (function () {
             })
             .text('\ue807');
 
+        // restricted icon background
+        processor.append('circle')
+            .attr({
+                'r': 9,
+                'cx': 12,
+                'cy': 12,
+                'class': 'restricted-background'
+            });
+
+        // restricted icon
+        processor.append('text')
+            .attr({
+                'x': 7.75,
+                'y': 17,
+                'class': 'restricted'
+            })
+            .text('\uf132');
+
         // make processors selectable
         processor.call(nf.Selectable.activate).call(nf.ContextMenu.activate);
     };
@@ -603,10 +621,27 @@ nf.Processor = (function () {
 
                     return color;
                 });
+
+            // restricted component indicator
+            processor.select('circle.restricted-background').style('visibility', showRestricted);
+            processor.select('text.restricted').style('visibility', showRestricted);
         });
     };
 
     /**
+     * Returns whether the resticted indicator should be shown for a given
+     * @param d
+     * @returns {*}
+     */
+    var showRestricted = function (d) {
+        if (!d.permissions.canRead) {
+            return 'hidden';
+        }
+
+        return d.component.restricted ? 'visible' : 'hidden';
+    }
+
+    /**
      * Updates the stats for the processors in the specified selection.
      *
      * @param {selection} updated           The processors to update

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
index ed70367..d41752e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
@@ -156,6 +156,15 @@ nf.Settings = (function () {
     };
 
     /**
+     * Whether the specified item is selectable.
+     *
+     * @param item reporting task type
+     */
+    var isSelectable = function (item) {
+        return nf.Common.isBlank(item.usageRestriction) || nf.Common.canAccessRestrictedComponents();
+    };
+
+    /**
      * Formatter for the name column.
      *
      * @param {type} row
@@ -406,7 +415,17 @@ nf.Settings = (function () {
         $('#reporting-task-type-filter').on('keyup', function (e) {
             var code = e.keyCode ? e.keyCode : e.which;
             if (code === $.ui.keyCode.ENTER) {
-                addSelectedReportingTask();
+                // get the grid reference
+                var grid = $('#reporting-task-types-table').data('gridInstance');
+                var selected = grid.getSelectedRows();
+
+                if (selected.length > 0) {
+                    // grid configured with multi-select = false
+                    var item = grid.getDataItem(selected[0]);
+                    if (isSelectable(item)) {
+                        addSelectedReportingTask();
+                    }
+                }
             } else {
                 applyReportingTaskTypeFilter();
             }
@@ -414,7 +433,7 @@ nf.Settings = (function () {
 
         // initialize the processor type table
         var reportingTaskTypesColumns = [
-            {id: 'type', name: 'Type', field: 'label', sortable: false, resizable: true},
+            {id: 'type', name: 'Type', field: 'label', formatter: nf.Common.typeFormatter, sortable: false, resizable: true},
             {id: 'tags', name: 'Tags', field: 'tags', sortable: false, resizable: true}
         ];
 
@@ -458,12 +477,21 @@ nf.Settings = (function () {
                     $('#reporting-task-type-name').text(reportingTaskType.label).ellipsis();
                     $('#selected-reporting-task-name').text(reportingTaskType.label);
                     $('#selected-reporting-task-type').text(reportingTaskType.type);
+
+                    // refresh the buttons based on the current selection
+                    $('#new-reporting-task-dialog').modal('refreshButtons');
                 }
             }
         });
         reportingTaskTypesGrid.onDblClick.subscribe(function (e, args) {
             var reportingTaskType = reportingTaskTypesGrid.getDataItem(args.row);
-            addReportingTask(reportingTaskType.type);
+
+            if (isSelectable(reportingTaskType)) {
+                addReportingTask(reportingTaskType.type);
+            }
+        });
+        reportingTaskTypesGrid.onViewportChanged.subscribe(function (e, args) {
+            nf.Common.cleanUpTooltips($('#reporting-task-types-table'), 'div.view-usage-restriction');
         });
 
         // wire up the dataview to the grid
@@ -481,7 +509,31 @@ nf.Settings = (function () {
         reportingTaskTypesData.syncGridSelection(reportingTaskTypesGrid, true);
 
         // hold onto an instance of the grid
-        $('#reporting-task-types-table').data('gridInstance', reportingTaskTypesGrid);
+        $('#reporting-task-types-table').data('gridInstance', reportingTaskTypesGrid).on('mouseenter', 'div.slick-cell', function (e) {
+            var usageRestriction = $(this).find('div.view-usage-restriction');
+            if (usageRestriction.length && !usageRestriction.data('qtip')) {
+                var rowId = $(this).find('span.row-id').text();
+
+                // get the status item
+                var item = reportingTaskTypesData.getItemById(rowId);
+
+                // show the tooltip
+                if (nf.Common.isDefinedAndNotNull(item.usageRestriction)) {
+                    usageRestriction.qtip($.extend({}, nf.Common.config.tooltipConfig, {
+                        content: item.usageRestriction,
+                        position: {
+                            container: $('#summary'),
+                            at: 'bottom right',
+                            my: 'top left',
+                            adjust: {
+                                x: 4,
+                                y: 4
+                            }
+                        }
+                    }));
+                }
+            }
+        });
 
         // load the available reporting tasks
         $.ajax({
@@ -503,6 +555,7 @@ nf.Settings = (function () {
                     label: nf.Common.substringAfterLast(documentedType.type, '.'),
                     type: documentedType.type,
                     description: nf.Common.escapeHtml(documentedType.description),
+                    usageRestriction: nf.Common.escapeHtml(documentedType.usageRestriction),
                     tags: documentedType.tags.join(', ')
                 });
 
@@ -537,6 +590,17 @@ nf.Settings = (function () {
                         hover: '#004849',
                         text: '#ffffff'
                     },
+                    disabled: function () {
+                        var selected = reportingTaskTypesGrid.getSelectedRows();
+
+                        if (selected.length > 0) {
+                            // grid configured with multi-select = false
+                            var item = reportingTaskTypesGrid.getDataItem(selected[0]);
+                            return isSelectable(item) === false;
+                        } else {
+                            return false;
+                        }
+                    },
                     handler: {
                         click: function () {
                             addSelectedReportingTask();

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
index 5d7054c..b0fdb3e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
@@ -91,6 +91,10 @@ nf.Common = (function () {
         value: 'provenance',
         description: 'Allows users to submit a Provenance Search and request Event Lineage'
     }, {
+        text: 'access restricted components',
+        value: 'restricted-components',
+        description: 'Allows users to create/modify restricted components assuming otherwise sufficient permissions'
+    }, {
         text: 'access all policies',
         value: 'policies',
         description: 'Allows users to view/modify the policies for all components'
@@ -157,6 +161,32 @@ nf.Common = (function () {
         currentUser: undefined,
 
         /**
+         * Formats type of a component for a new instance dialog.
+         *
+         * @param row
+         * @param cell
+         * @param value
+         * @param columnDef
+         * @param dataContext
+         * @returns {string}
+         */
+        typeFormatter: function (row, cell, value, columnDef, dataContext) {
+            var markup = '';
+
+            // restriction
+            if (nf.Common.isBlank(dataContext.usageRestriction) === false) {
+                markup += '<div class="view-usage-restriction fa fa-shield"></div><span class="hidden row-id">' + nf.Common.escapeHtml(dataContext.id) + '</span>';
+            } else {
+                markup += '<div class="fa"></div>';
+            }
+
+            // type
+            markup += value;
+
+            return markup;
+        },
+
+        /**
          * Sets the current user.
          * 
          * @param currentUser
@@ -272,6 +302,19 @@ nf.Common = (function () {
         },
 
         /**
+         * Determines whether the current user can access restricted comopnents.
+         *
+         * @returns {boolean}
+         */
+        canAccessRestrictedComponents: function () {
+            if (nf.Common.isDefinedAndNotNull(nf.Common.currentUser)) {
+                return nf.Common.currentUser.restrictedComponentsPermissions.canWrite === true;
+            } else {
+                return false;
+            }
+        },
+
+        /**
          * Determines whether the current user can access counters.
          * 
          * @returns {boolean}

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-hadoop-bundle/nifi-hdfs-processors/src/main/java/org/apache/nifi/processors/hadoop/DeleteHDFS.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-hadoop-bundle/nifi-hdfs-processors/src/main/java/org/apache/nifi/processors/hadoop/DeleteHDFS.java b/nifi-nar-bundles/nifi-hadoop-bundle/nifi-hdfs-processors/src/main/java/org/apache/nifi/processors/hadoop/DeleteHDFS.java
index 371b9e1..ed4d10d 100644
--- a/nifi-nar-bundles/nifi-hadoop-bundle/nifi-hdfs-processors/src/main/java/org/apache/nifi/processors/hadoop/DeleteHDFS.java
+++ b/nifi-nar-bundles/nifi-hadoop-bundle/nifi-hdfs-processors/src/main/java/org/apache/nifi/processors/hadoop/DeleteHDFS.java
@@ -16,20 +16,13 @@
  */
 package org.apache.nifi.processors.hadoop;
 
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 import org.apache.hadoop.fs.FileStatus;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.nifi.annotation.behavior.InputRequirement;
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.behavior.TriggerWhenEmpty;
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
 import org.apache.nifi.annotation.documentation.Tags;
@@ -41,16 +34,24 @@ import org.apache.nifi.processor.Relationship;
 import org.apache.nifi.processor.exception.ProcessException;
 import org.apache.nifi.processor.util.StandardValidators;
 
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 @TriggerWhenEmpty
 @InputRequirement(InputRequirement.Requirement.INPUT_ALLOWED)
-@Tags({ "hadoop", "HDFS", "delete", "remove", "filesystem" })
+@Tags({ "hadoop", "HDFS", "delete", "remove", "filesystem", "restricted" })
 @CapabilityDescription("Deletes a file from HDFS. The file can be provided as an attribute from an incoming FlowFile, "
         + "or a statically set file that is periodically removed. If this processor has an incoming connection, it"
         + "will ignore running on a periodic basis and instead rely on incoming FlowFiles to trigger a delete. "
         + "Optionally, you may specify use a wildcard character to match multiple files or directories.")
+@Restricted("Provides operator the ability to delete any file that NiFi has access to in HDFS or the local filesystem.")
 public class DeleteHDFS extends AbstractHadoopProcessor {
     public static final Relationship REL_SUCCESS = new Relationship.Builder()
             .name("success")


[3/3] nifi git commit: NIFI-3050: Implemented access control logic for restricted components.

Posted by al...@apache.org.
NIFI-3050: Implemented access control logic for restricted components.

- Addressing comments from PR.
- Adding restricted tags to relevant components.
- Showing a restricted icon overlay on the processor node on the canvas. (+1 squashed commit)
Squashed commits:
[f487682] NIFI-3050:
- Introducing a Restricted annotation for components that require elevated privileges to use.
- Updating the new Processor, Controller Service, and Reporting Task dialogs to include these details and prevent unauthorized selection.
- Including the Restricted description in the generated component documentation.
- Updating processor access control integration test to verify restricted component creation.
- Updating the developer, user, and admin guide to include the restricted component policy.

This closes #1247.

Signed-off-by: Andy LoPresto <al...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/7f5eabd6
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/7f5eabd6
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/7f5eabd6

Branch: refs/heads/master
Commit: 7f5eabd603bfc326dadc35590bbe69304e8c90fa
Parents: eb5abf8
Author: Matt Gilman <ma...@gmail.com>
Authored: Fri Nov 18 16:51:13 2016 -0500
Committer: Andy LoPresto <al...@apache.org>
Committed: Mon Nov 21 12:07:48 2016 -0800

----------------------------------------------------------------------
 .../nifi/annotation/behavior/Restricted.java    |  51 +++++++++
 .../src/main/asciidoc/administration-guide.adoc |   5 +
 .../src/main/asciidoc/developer-guide.adoc      |  17 +++
 .../src/main/asciidoc/images/restricted.png     | Bin 0 -> 3621 bytes
 nifi-docs/src/main/asciidoc/user-guide.adoc     |  16 ++-
 .../nifi/processors/flume/ExecuteFlumeSink.java |  15 +--
 .../processors/flume/ExecuteFlumeSource.java    |  17 +--
 .../nifi/web/api/dto/ControllerServiceDTO.java  |  25 +++--
 .../nifi/web/api/dto/DocumentedTypeDTO.java     |  18 +++-
 .../apache/nifi/web/api/dto/ProcessorDTO.java   |  18 +++-
 .../nifi/web/api/dto/ReportingTaskDTO.java      |  19 +++-
 .../nifi/web/api/entity/CurrentUserEntity.java  |  13 +++
 .../html/HtmlDocumentationWriter.java           |  41 ++++++--
 .../FullyDocumentedControllerService.java       |  10 +-
 .../example/FullyDocumentedProcessor.java       |  14 +--
 .../example/FullyDocumentedReportingTask.java   |  12 ++-
 .../html/HtmlDocumentationWriterTest.java       |  18 ++--
 .../html/ProcessorDocumentationWriterTest.java  |  14 +--
 .../nifi/authorization/FileAuthorizer.java      |   3 +
 .../nifi/authorization/RoleAccessPolicy.java    |   1 +
 .../nifi/authorization/FileAuthorizerTest.java  |   8 +-
 .../authorization/resource/ResourceFactory.java |  21 ++++
 .../authorization/resource/ResourceType.java    |   1 +
 .../RestrictedComponentsAuthorizable.java       |  33 ++++++
 .../nifi/controller/ConfiguredComponent.java    |  40 +++++++
 .../nifi/controller/StandardProcessorNode.java  |   8 +-
 .../reporting/StandardReportingTaskNode.java    |   6 ++
 .../service/StandardControllerServiceNode.java  |   6 ++
 .../nifi/authorization/AuthorizableLookup.java  |  18 ++--
 .../AuthorizeControllerServiceReference.java    |   2 +-
 .../ConfigurableComponentAuthorizable.java      |  55 ++++++++++
 ...ServiceReferencingComponentAuthorizable.java |  48 ---------
 .../StandardAuthorizableLookup.java             | 104 ++++++++++---------
 .../nifi/web/StandardNiFiServiceFacade.java     |   1 +
 .../StandardNiFiWebConfigurationContext.java    |   8 +-
 .../apache/nifi/web/api/ControllerResource.java |  14 ++-
 .../nifi/web/api/ControllerServiceResource.java |   4 +-
 .../nifi/web/api/ProcessGroupResource.java      |  22 +++-
 .../apache/nifi/web/api/ProcessorResource.java  |   4 +-
 .../nifi/web/api/ReportingTaskResource.java     |   4 +-
 .../org/apache/nifi/web/api/dto/DtoFactory.java |  10 ++
 .../nifi/web/controller/ControllerFacade.java   |   1 +
 .../accesscontrol/AccessControlHelper.java      |   6 ++
 .../accesscontrol/ITProcessorAccessControl.java |  38 +++++++
 .../integration/util/NiFiTestAuthorizer.java    |  14 ++-
 .../integration/util/RestrictedProcessor.java   |  51 +++++++++
 .../src/main/webapp/css/common-ui.css           |   8 +-
 .../nifi-web-ui/src/main/webapp/css/graph.css   |  12 +++
 .../main/webapp/css/new-processor-dialog.css    |   8 ++
 .../src/main/webapp/css/policy-management.css   |   2 +-
 .../main/webapp/js/jquery/modal/jquery.modal.js |  77 +++++++++++---
 .../components/nf-ng-processor-component.js     |  74 +++++++++++--
 .../js/nf/canvas/nf-controller-services.js      |  73 ++++++++++++-
 .../webapp/js/nf/canvas/nf-policy-management.js |   5 +-
 .../main/webapp/js/nf/canvas/nf-processor.js    |  35 +++++++
 .../src/main/webapp/js/nf/canvas/nf-settings.js |  72 ++++++++++++-
 .../src/main/webapp/js/nf/nf-common.js          |  43 ++++++++
 .../nifi/processors/hadoop/DeleteHDFS.java      |  27 ++---
 .../nifi/processors/hadoop/FetchHDFS.java       |   4 +-
 .../apache/nifi/processors/hadoop/GetHDFS.java  |   4 +-
 .../apache/nifi/processors/hadoop/PutHDFS.java  |   4 +-
 .../nifi/processors/script/ExecuteScript.java   |  35 ++++---
 .../script/InvokeScriptedProcessor.java         |  33 +++---
 .../SiteToSiteProvenanceReportingTask.java      |   4 +-
 .../processors/standard/ExecuteProcess.java     |  46 ++++----
 .../standard/ExecuteStreamCommand.java          |  36 ++++---
 .../nifi/processors/standard/FetchFile.java     |  34 +++---
 .../nifi/processors/standard/GetFile.java       |  47 +++++----
 .../nifi/processors/standard/ListFile.java      |  42 ++++----
 .../nifi/processors/standard/PutFile.java       |  40 +++----
 .../nifi/processors/standard/TailFile.java      |  62 +++++------
 71 files changed, 1258 insertions(+), 423 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-api/src/main/java/org/apache/nifi/annotation/behavior/Restricted.java
----------------------------------------------------------------------
diff --git a/nifi-api/src/main/java/org/apache/nifi/annotation/behavior/Restricted.java b/nifi-api/src/main/java/org/apache/nifi/annotation/behavior/Restricted.java
new file mode 100644
index 0000000..07d729d
--- /dev/null
+++ b/nifi-api/src/main/java/org/apache/nifi/annotation/behavior/Restricted.java
@@ -0,0 +1,51 @@
+/*
+ * 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.annotation.behavior;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * <p>
+ * Marks the usage of a component as restricted to users with elevated privileges.
+ * </p>
+ * <p>
+ * A {@code Restricted} component is one that can be used to execute arbitrary unsanitized
+ * code provided by the operator through the NiFi REST API/UI or can be used to obtain
+ * or alter data on the NiFi host system using the NiFi OS credentials. These components
+ * could be used by an otherwise authorized NiFi user to go beyond the intended use of
+ * the application, escalate privilege, or could expose data about the internals of the
+ * NiFi process or the host system. All of these capabilities should be considered
+ * privileged, and admins should be aware of these capabilities and explicitly enable
+ * them for a subset of trusted users.
+ * </p>
+ */
+@Documented
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+public @interface Restricted {
+    /**
+     * Provides a description of why the component usage is restricted
+     */
+    String value();
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-docs/src/main/asciidoc/administration-guide.adoc
----------------------------------------------------------------------
diff --git a/nifi-docs/src/main/asciidoc/administration-guide.adoc b/nifi-docs/src/main/asciidoc/administration-guide.adoc
index 6bf8547..b386088 100644
--- a/nifi-docs/src/main/asciidoc/administration-guide.adoc
+++ b/nifi-docs/src/main/asciidoc/administration-guide.adoc
@@ -481,6 +481,7 @@ Here is a summary of policies assigned to each legacy role if the NiFi instance
 |view policies                 |*      |     |         |            |      |
 |modify policies               |*      |     |         |            |      |
 |query provenance              |       |     |         |*           |      |
+|access restricted components  |       |*    |         |            |      |
 |view the data                 |       |*    |         |*           |      |*
 |modify the data               |       |*    |         |            |      |*
 |retrieve site-to-site details |       |     |         |            |*     |
@@ -584,6 +585,10 @@ Global access policies govern the following system level authorizations:
 |Allows users to submit a Provenance Search and request Event Lineage
 |Data Provenance
 
+|access restricted components
+|Allows users to create/modify restricted components assuming otherwise sufficient permissions
+|N/A
+
 |access all policies
 |Allows users to view/modify the policies for all components
 |Policies

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-docs/src/main/asciidoc/developer-guide.adoc
----------------------------------------------------------------------
diff --git a/nifi-docs/src/main/asciidoc/developer-guide.adoc b/nifi-docs/src/main/asciidoc/developer-guide.adoc
index 195b4f1..0f45c84 100644
--- a/nifi-docs/src/main/asciidoc/developer-guide.adoc
+++ b/nifi-docs/src/main/asciidoc/developer-guide.adoc
@@ -565,6 +565,23 @@ for instance, they should not be
 relied upon for critical business logic.
 
 
+[[restricted]]
+=== Restricted
+
+A Restricted component is one that can be used to execute arbitrary unsanitized code provided by the operator
+through the NiFi REST API/UI or can be used to obtain or alter data on the NiFi host system using the NiFi OS
+credentials. These components could be used by an otherwise authorized NiFi user to go beyond the intended use of
+the application, escalate privilege, or could expose data about the internals of the NiFi process or the host
+system. All of these capabilities should be considered privileged, and admins should be aware of these
+capabilities and explicitly enable them for a subset of trusted users.
+
+A Processor, Controller Service, or Reporting Task can be marked with the @Restricted annotation. This
+will result in the component being treated as restricted and will require a user to be explicitly added to the
+list of users who can access restricted components. Once a user is permitted to access restricted components,
+they will be allowed to create and modify those components assuming all other permissions are permitted.
+Without access to restricted components, a user will be still be aware these types of components exist but will
+be unable to create or modify them even with otherwise sufficient permissions.
+
 [[state_manager]]
 === State Manager
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-docs/src/main/asciidoc/images/restricted.png
----------------------------------------------------------------------
diff --git a/nifi-docs/src/main/asciidoc/images/restricted.png b/nifi-docs/src/main/asciidoc/images/restricted.png
new file mode 100644
index 0000000..fe6d716
Binary files /dev/null and b/nifi-docs/src/main/asciidoc/images/restricted.png differ

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-docs/src/main/asciidoc/user-guide.adoc
----------------------------------------------------------------------
diff --git a/nifi-docs/src/main/asciidoc/user-guide.adoc b/nifi-docs/src/main/asciidoc/user-guide.adoc
index 34a03e0..b64454c 100644
--- a/nifi-docs/src/main/asciidoc/user-guide.adoc
+++ b/nifi-docs/src/main/asciidoc/user-guide.adoc
@@ -40,15 +40,13 @@ Browser Support
 |Browser  |Version
 |Chrome   |Current and Current - 1
 |FireFox  |Current and Current - 1
-|Edge     |Current
+|Edge     |Current and Current - 1
 |Safari   |Current and Current - 1
 |======================
 
 Current and Current - 1 indicates that the UI is supported in the current stable release of that browser and the preceding one. For instance, if
 the current stable release is 45.X then the officially supported versions will be 45.X and 44.X.
 
-Current indicates that the UI is supported in the current stable release of that browser.
-
 The supported browser versions are driven by the capabilities the UI employs and the dependencies it uses. UI features will be developed and tested
 against the supported browsers. Any problem using a supported browser should be reported to Apache NiFi.
 
@@ -195,6 +193,7 @@ The available global access policies are:
 |view the UI   |Allows users to view the UI
 |access the controller  |Allows users to view and modify the controller including reporting tasks, Controller Services, and nodes in the cluster
 |query provenance     |Allows users to submit a provenance search and request even lineage
+|access restricted components     |Allows users to create/modify restricted components assuming otherwise sufficient permissions
 |access all policies   |Allows users to view and modify the policies for all components
 |access users/groups   |Allows users view and modify the users and user groups
 |retrieve site-to-site details | Allows other NiFi instances to retrieve Site-To-Site details
@@ -270,6 +269,17 @@ Processors that allow us to ingest data via HTTP, we can select both the `http`
 
 image::add-processor-with-tag-cloud.png["Add Processor with Tag Cloud"]
 
+Restricted components will be marked with a
+image:restricted.png["Restricted"]
+icon next to their name. These are components that can be used to execute arbitrary unsanitized code provided by the operator
+through the NiFi REST API/UI or can be used to obtain or alter data on the NiFi host system using the NiFi OS credentials.
+These components could be used by an otherwise authorized NiFi user to go beyond the intended use of the application, escalate
+privilege, or could expose data about the internals of the NiFi process or the host system. All of these capabilities should
+be considered privileged, and admins should be aware of these capabilities and explicitly enable them for a subset of trusted users.
+
+Before a user is allowed to create and modify restricted components they must be granted access to restricted components. Refer to
+<<UI-with-multi-tenant-authorization,multi-tenant>> documentation.
+
 Clicking the `Add` button or double-clicking on a Processor Type will add the selected Processor to the canvas at the
 location that it was dropped.
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-flume-bundle/nifi-flume-processors/src/main/java/org/apache/nifi/processors/flume/ExecuteFlumeSink.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-flume-bundle/nifi-flume-processors/src/main/java/org/apache/nifi/processors/flume/ExecuteFlumeSink.java b/nifi-nar-bundles/nifi-flume-bundle/nifi-flume-processors/src/main/java/org/apache/nifi/processors/flume/ExecuteFlumeSink.java
index e40608d..ec99acb 100644
--- a/nifi-nar-bundles/nifi-flume-bundle/nifi-flume-processors/src/main/java/org/apache/nifi/processors/flume/ExecuteFlumeSink.java
+++ b/nifi-nar-bundles/nifi-flume-bundle/nifi-flume-processors/src/main/java/org/apache/nifi/processors/flume/ExecuteFlumeSink.java
@@ -16,14 +16,15 @@
  */
 package org.apache.nifi.processors.flume;
 
-import java.util.List;
-import java.util.Set;
-
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
 import org.apache.flume.EventDeliveryException;
 import org.apache.flume.Sink;
 import org.apache.flume.conf.Configurables;
 import org.apache.nifi.annotation.behavior.InputRequirement;
 import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.behavior.TriggerSerially;
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
 import org.apache.nifi.annotation.documentation.Tags;
@@ -38,17 +39,17 @@ import org.apache.nifi.processor.Relationship;
 import org.apache.nifi.processor.exception.ProcessException;
 import org.apache.nifi.processor.util.StandardValidators;
 
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
+import java.util.List;
+import java.util.Set;
 
 /**
  * This processor runs a Flume sink
  */
 @TriggerSerially
-@Tags({"flume", "hadoop", "put", "sink"})
+@Tags({"flume", "hadoop", "put", "sink", "restricted"})
 @InputRequirement(Requirement.INPUT_REQUIRED)
 @CapabilityDescription("Execute a Flume sink. Each input FlowFile is converted into a Flume Event for processing by the sink.")
+@Restricted("Provides operator the ability to execute arbitrary Flume configurations assuming all permissions that NiFi has.")
 public class ExecuteFlumeSink extends AbstractFlumeProcessor {
 
     public static final PropertyDescriptor SINK_TYPE = new PropertyDescriptor.Builder()

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-flume-bundle/nifi-flume-processors/src/main/java/org/apache/nifi/processors/flume/ExecuteFlumeSource.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-flume-bundle/nifi-flume-processors/src/main/java/org/apache/nifi/processors/flume/ExecuteFlumeSource.java b/nifi-nar-bundles/nifi-flume-bundle/nifi-flume-processors/src/main/java/org/apache/nifi/processors/flume/ExecuteFlumeSource.java
index 3ef72ff..63ed190 100644
--- a/nifi-nar-bundles/nifi-flume-bundle/nifi-flume-processors/src/main/java/org/apache/nifi/processors/flume/ExecuteFlumeSource.java
+++ b/nifi-nar-bundles/nifi-flume-bundle/nifi-flume-processors/src/main/java/org/apache/nifi/processors/flume/ExecuteFlumeSource.java
@@ -16,10 +16,9 @@
  */
 package org.apache.nifi.processors.flume;
 
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicReference;
-
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
 import org.apache.flume.EventDeliveryException;
 import org.apache.flume.EventDrivenSource;
 import org.apache.flume.PollableSource;
@@ -29,6 +28,7 @@ import org.apache.flume.conf.Configurables;
 import org.apache.flume.source.EventDrivenSourceRunner;
 import org.apache.nifi.annotation.behavior.InputRequirement;
 import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.behavior.TriggerSerially;
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
 import org.apache.nifi.annotation.documentation.Tags;
@@ -44,17 +44,18 @@ import org.apache.nifi.processor.Relationship;
 import org.apache.nifi.processor.exception.ProcessException;
 import org.apache.nifi.processor.util.StandardValidators;
 
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * This processor runs a Flume source
  */
 @TriggerSerially
-@Tags({"flume", "hadoop", "get", "source"})
+@Tags({"flume", "hadoop", "get", "source", "restricted"})
 @InputRequirement(Requirement.INPUT_FORBIDDEN)
 @CapabilityDescription("Execute a Flume source. Each Flume Event is sent to the success relationship as a FlowFile")
+@Restricted("Provides operator the ability to execute arbitrary Flume configurations assuming all permissions that NiFi has.")
 public class ExecuteFlumeSource extends AbstractFlumeProcessor {
 
     public static final PropertyDescriptor SOURCE_TYPE = new PropertyDescriptor.Builder()

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceDTO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceDTO.java
index 9f2f74a..778128f 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceDTO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceDTO.java
@@ -16,16 +16,14 @@
  */
 package org.apache.nifi.web.api.dto;
 
+import com.wordnik.swagger.annotations.ApiModelProperty;
+import org.apache.nifi.web.api.entity.ControllerServiceReferencingComponentEntity;
+
+import javax.xml.bind.annotation.XmlType;
 import java.util.Collection;
 import java.util.Map;
 import java.util.Set;
 
-import javax.xml.bind.annotation.XmlType;
-
-import org.apache.nifi.web.api.entity.ControllerServiceReferencingComponentEntity;
-
-import com.wordnik.swagger.annotations.ApiModelProperty;
-
 /**
  * A Controller Service that can be shared by other components
  */
@@ -37,6 +35,7 @@ public class ControllerServiceDTO extends ComponentDTO {
     private String comments;
     private String state;
     private Boolean persistsState;
+    private Boolean restricted;
 
     private Map<String, String> properties;
     private Map<String, PropertyDescriptorDTO> descriptors;
@@ -105,6 +104,20 @@ public class ControllerServiceDTO extends ComponentDTO {
     }
 
     /**
+     * @return whether this controller service requires elevated privileges
+     */
+    @ApiModelProperty(
+            value = "Whether the controller service requires elevated privileges."
+    )
+    public Boolean getRestricted() {
+        return restricted;
+    }
+
+    public void setRestricted(Boolean restricted) {
+        this.restricted = restricted;
+    }
+
+    /**
      * @return The state of this controller service. Possible values are ENABLED, ENABLING, DISABLED, DISABLING
      */
     @ApiModelProperty(

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/DocumentedTypeDTO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/DocumentedTypeDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/DocumentedTypeDTO.java
index 67b26ca..dc0ea78 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/DocumentedTypeDTO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/DocumentedTypeDTO.java
@@ -17,8 +17,9 @@
 package org.apache.nifi.web.api.dto;
 
 import com.wordnik.swagger.annotations.ApiModelProperty;
-import java.util.Set;
+
 import javax.xml.bind.annotation.XmlType;
+import java.util.Set;
 
 /**
  * Class used for providing documentation of a specified type.
@@ -28,6 +29,7 @@ public class DocumentedTypeDTO {
 
     private String type;
     private String description;
+    private String usageRestriction;
     private Set<String> tags;
 
     /**
@@ -45,6 +47,20 @@ public class DocumentedTypeDTO {
     }
 
     /**
+     * @return An optional description of why the usage of this component is restricted
+     */
+    @ApiModelProperty(
+            value = "The description of why the usage of this component is restricted."
+    )
+    public String getUsageRestriction() {
+        return usageRestriction;
+    }
+
+    public void setUsageRestriction(String usageRestriction) {
+        this.usageRestriction = usageRestriction;
+    }
+
+    /**
      * @return The type is the fully-qualified name of a Java class
      */
     @ApiModelProperty(

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessorDTO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessorDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessorDTO.java
index 38053ce..ee641c9 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessorDTO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessorDTO.java
@@ -17,10 +17,11 @@
 package org.apache.nifi.web.api.dto;
 
 import com.wordnik.swagger.annotations.ApiModelProperty;
+
+import javax.xml.bind.annotation.XmlType;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
-import javax.xml.bind.annotation.XmlType;
 
 /**
  * Details for a processor within this NiFi.
@@ -38,6 +39,7 @@ public class ProcessorDTO extends ComponentDTO {
     private Boolean supportsEventDriven;
     private Boolean supportsBatching;
     private Boolean persistsState;
+    private Boolean restricted;
     private String inputRequirement;
 
     private ProcessorConfigDTO config;
@@ -138,6 +140,20 @@ public class ProcessorDTO extends ComponentDTO {
     }
 
     /**
+     * @return whether this processor requires elevated privileges
+     */
+    @ApiModelProperty(
+            value = "Whether the processor requires elevated privileges."
+    )
+    public Boolean getRestricted() {
+        return restricted;
+    }
+
+    public void setRestricted(Boolean restricted) {
+        this.restricted = restricted;
+    }
+
+    /**
      * @return the input requirement of this processor
      */
     @ApiModelProperty(

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ReportingTaskDTO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ReportingTaskDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ReportingTaskDTO.java
index e5afe6e..203fd0e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ReportingTaskDTO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ReportingTaskDTO.java
@@ -17,10 +17,10 @@
 package org.apache.nifi.web.api.dto;
 
 import com.wordnik.swagger.annotations.ApiModelProperty;
-import java.util.Collection;
-import java.util.Map;
 
 import javax.xml.bind.annotation.XmlType;
+import java.util.Collection;
+import java.util.Map;
 
 /**
  * Component that is capable of reporting internal NiFi state to an external service
@@ -33,6 +33,7 @@ public class ReportingTaskDTO extends ComponentDTO {
     private String state;
     private String comments;
     private Boolean persistsState;
+    private Boolean restricted;
 
     private String schedulingPeriod;
     private String schedulingStrategy;
@@ -120,6 +121,20 @@ public class ReportingTaskDTO extends ComponentDTO {
     }
 
     /**
+     * @return whether this reporting task requires elevated privileges
+     */
+    @ApiModelProperty(
+            value = "Whether the reporting task requires elevated privileges."
+    )
+    public Boolean getRestricted() {
+        return restricted;
+    }
+
+    public void setRestricted(Boolean restricted) {
+        this.restricted = restricted;
+    }
+
+    /**
      * @return current scheduling state of the reporting task
      */
     @ApiModelProperty(

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/CurrentUserEntity.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/CurrentUserEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/CurrentUserEntity.java
index 76a692e..d24ce67 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/CurrentUserEntity.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/CurrentUserEntity.java
@@ -36,6 +36,7 @@ public class CurrentUserEntity extends Entity {
     private PermissionsDTO controllerPermissions;
     private PermissionsDTO policiesPermissions;
     private PermissionsDTO systemPermissions;
+    private PermissionsDTO restrictedComponentsPermissions;
 
     /**
      * @return the user identity being serialized
@@ -132,4 +133,16 @@ public class CurrentUserEntity extends Entity {
     public void setSystemPermissions(PermissionsDTO systemPermissions) {
         this.systemPermissions = systemPermissions;
     }
+
+    /**
+     * @return permissions for accessing the restricted components
+     */
+    @ApiModelProperty("Permissions for accessing restricted components. Note: the read permission are not used and will always be false.")
+    public PermissionsDTO getRestrictedComponentsPermissions() {
+        return restrictedComponentsPermissions;
+    }
+
+    public void setRestrictedComponentsPermissions(PermissionsDTO restrictedComponentsPermissions) {
+        this.restrictedComponentsPermissions = restrictedComponentsPermissions;
+    }
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/html/HtmlDocumentationWriter.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/html/HtmlDocumentationWriter.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/html/HtmlDocumentationWriter.java
index 236ff83..9a60c27 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/html/HtmlDocumentationWriter.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/html/HtmlDocumentationWriter.java
@@ -16,19 +16,9 @@
  */
 package org.apache.nifi.documentation.html;
 
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-import javax.xml.stream.FactoryConfigurationError;
-import javax.xml.stream.XMLOutputFactory;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamWriter;
-
 import org.apache.nifi.annotation.behavior.DynamicProperties;
 import org.apache.nifi.annotation.behavior.DynamicProperty;
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.behavior.Stateful;
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
 import org.apache.nifi.annotation.documentation.SeeAlso;
@@ -40,6 +30,16 @@ import org.apache.nifi.controller.ControllerService;
 import org.apache.nifi.documentation.DocumentationWriter;
 import org.apache.nifi.nar.ExtensionManager;
 
+import javax.xml.stream.FactoryConfigurationError;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
 /**
  * Generates HTML documentation for a ConfigurableComponent. This class is used
  * to generate documentation for ControllerService and ReportingTask because
@@ -129,6 +129,7 @@ public class HtmlDocumentationWriter implements DocumentationWriter {
         writeDynamicProperties(configurableComponent, xmlStreamWriter);
         writeAdditionalBodyInfo(configurableComponent, xmlStreamWriter);
         writeStatefulInfo(configurableComponent, xmlStreamWriter);
+        writeRestrictedInfo(configurableComponent, xmlStreamWriter);
         writeSeeAlso(configurableComponent, xmlStreamWriter);
         xmlStreamWriter.writeEndElement();
     }
@@ -166,6 +167,24 @@ public class HtmlDocumentationWriter implements DocumentationWriter {
     }
 
     /**
+     * Write the description of the Restricted annotation if provided in this component.
+     *
+     * @param configurableComponent the component to describe
+     * @param xmlStreamWriter the stream writer to use
+     * @throws XMLStreamException thrown if there was a problem writing the XML
+     */
+    private void writeRestrictedInfo(ConfigurableComponent configurableComponent, XMLStreamWriter xmlStreamWriter)
+            throws XMLStreamException {
+        final Restricted restricted = configurableComponent.getClass().getAnnotation(Restricted.class);
+
+        writeSimpleElement(xmlStreamWriter, "h3", "Restricted: ");
+
+        if(restricted != null) {
+            writeSimpleElement(xmlStreamWriter, "td", restricted.value());
+        }
+    }
+
+    /**
      * Writes the list of components that may be linked from this component.
      *
      * @param configurableComponent the component to describe

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedControllerService.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedControllerService.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedControllerService.java
index 195a75b..62e12a8 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedControllerService.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedControllerService.java
@@ -16,10 +16,7 @@
  */
 package org.apache.nifi.documentation.example;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
 import org.apache.nifi.annotation.documentation.Tags;
 import org.apache.nifi.annotation.lifecycle.OnRemoved;
@@ -29,8 +26,13 @@ import org.apache.nifi.controller.AbstractControllerService;
 import org.apache.nifi.controller.ConfigurationContext;
 import org.apache.nifi.processor.util.StandardValidators;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
 @CapabilityDescription("A documented controller service that can help you do things")
 @Tags({ "one", "two", "three" })
+@Restricted("controller service restriction description")
 public class FullyDocumentedControllerService extends AbstractControllerService implements SampleService {
 
     public static final PropertyDescriptor KEYSTORE = new PropertyDescriptor.Builder().name("Keystore Filename").description("The fully-qualified filename of the Keystore").defaultValue(null)

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedProcessor.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedProcessor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedProcessor.java
index af668ba..bc1be1f 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedProcessor.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedProcessor.java
@@ -16,15 +16,10 @@
  */
 package org.apache.nifi.documentation.example;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
 import org.apache.nifi.annotation.behavior.DynamicProperty;
 import org.apache.nifi.annotation.behavior.DynamicRelationship;
 import org.apache.nifi.annotation.behavior.ReadsAttribute;
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.behavior.Stateful;
 import org.apache.nifi.annotation.behavior.WritesAttribute;
 import org.apache.nifi.annotation.behavior.WritesAttributes;
@@ -44,6 +39,12 @@ import org.apache.nifi.processor.Relationship;
 import org.apache.nifi.processor.exception.ProcessException;
 import org.apache.nifi.processor.util.StandardValidators;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
 @Tags({"one", "two", "three"})
 @CapabilityDescription("This is a processor that is used to test documentation.")
 @WritesAttributes({
@@ -54,6 +55,7 @@ import org.apache.nifi.processor.util.StandardValidators;
 @DynamicProperty(name = "Relationship Name", supportsExpressionLanguage = true, value = "some XPath", description = "Routes FlowFiles to relationships based on XPath")
 @DynamicRelationship(name = "name from dynamic property", description = "all files that match the properties XPath")
 @Stateful(scopes = {Scope.CLUSTER, Scope.LOCAL}, description = "state management description")
+@Restricted("processor restriction description")
 public class FullyDocumentedProcessor extends AbstractProcessor {
 
     public static final PropertyDescriptor DIRECTORY = new PropertyDescriptor.Builder().name("Input Directory")

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedReportingTask.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedReportingTask.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedReportingTask.java
index 28a6dc6..64118bf 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedReportingTask.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedReportingTask.java
@@ -16,20 +16,22 @@
  */
 package org.apache.nifi.documentation.example;
 
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.nifi.components.PropertyDescriptor;
-import org.apache.nifi.controller.ConfigurationContext;
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
 import org.apache.nifi.annotation.documentation.Tags;
 import org.apache.nifi.annotation.lifecycle.OnRemoved;
 import org.apache.nifi.annotation.lifecycle.OnShutdown;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.controller.ConfigurationContext;
 import org.apache.nifi.reporting.AbstractReportingTask;
 import org.apache.nifi.reporting.ReportingContext;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @CapabilityDescription("A helper reporting task to do...")
 @Tags({"first", "second", "third"})
+@Restricted("reporting task restriction description")
 public class FullyDocumentedReportingTask extends AbstractReportingTask {
 
     public static final PropertyDescriptor SHOW_DELTAS = new PropertyDescriptor.Builder()

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/html/HtmlDocumentationWriterTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/html/HtmlDocumentationWriterTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/html/HtmlDocumentationWriterTest.java
index 2bd9def..0402a9f 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/html/HtmlDocumentationWriterTest.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/html/HtmlDocumentationWriterTest.java
@@ -16,12 +16,6 @@
  */
 package org.apache.nifi.documentation.html;
 
-import static org.apache.nifi.documentation.html.XmlValidator.assertContains;
-import static org.junit.Assert.assertEquals;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
 import org.apache.nifi.controller.ControllerService;
 import org.apache.nifi.documentation.DocumentationWriter;
 import org.apache.nifi.documentation.example.ControllerServiceWithLogger;
@@ -37,6 +31,12 @@ import org.apache.nifi.reporting.ReportingTask;
 import org.junit.Assert;
 import org.junit.Test;
 
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import static org.apache.nifi.documentation.html.XmlValidator.assertContains;
+import static org.junit.Assert.assertEquals;
+
 public class HtmlDocumentationWriterTest {
 
     @Test
@@ -77,6 +77,9 @@ public class HtmlDocumentationWriterTest {
         assertContains(results, "PKCS12");
         assertContains(results, "Sensitive Property: true");
 
+        // restricted
+        assertContains(results, "controller service restriction description");
+
         // verify the right OnRemoved and OnShutdown methods were called
         Assert.assertEquals(0, controllerService.getOnRemovedArgs());
         Assert.assertEquals(0, controllerService.getOnRemovedNoArgs());
@@ -114,6 +117,9 @@ public class HtmlDocumentationWriterTest {
         assertContains(results, "true");
         assertContains(results, "false");
 
+        // restricted
+        assertContains(results, "reporting task restriction description");
+
         // verify the right OnRemoved and OnShutdown methods were called
         Assert.assertEquals(0, reportingTask.getOnRemovedArgs());
         Assert.assertEquals(0, reportingTask.getOnRemovedNoArgs());

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/html/ProcessorDocumentationWriterTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/html/ProcessorDocumentationWriterTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/html/ProcessorDocumentationWriterTest.java
index 7c6173a..61045b0 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/html/ProcessorDocumentationWriterTest.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/html/ProcessorDocumentationWriterTest.java
@@ -16,12 +16,6 @@
  */
 package org.apache.nifi.documentation.html;
 
-import static org.apache.nifi.documentation.html.XmlValidator.assertContains;
-import static org.apache.nifi.documentation.html.XmlValidator.assertNotContains;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
 import org.apache.nifi.documentation.DocumentationWriter;
 import org.apache.nifi.documentation.example.FullyDocumentedProcessor;
@@ -31,6 +25,12 @@ import org.apache.nifi.documentation.init.ProcessorInitializer;
 import org.junit.Assert;
 import org.junit.Test;
 
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import static org.apache.nifi.documentation.html.XmlValidator.assertContains;
+import static org.apache.nifi.documentation.html.XmlValidator.assertNotContains;
+
 public class ProcessorDocumentationWriterTest {
 
     @Test
@@ -69,6 +69,8 @@ public class ProcessorDocumentationWriterTest {
         assertContains(results, "CLUSTER, LOCAL");
         assertContains(results, "state management description");
 
+        assertContains(results, "processor restriction description");
+
         assertNotContains(results, "iconSecure.png");
         assertContains(results, FullyDocumentedProcessor.class.getAnnotation(CapabilityDescription.class)
                 .value());

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java
index 69733a8..7f89ddd 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java
@@ -333,6 +333,9 @@ public class FileAuthorizer extends AbstractPolicyBasedAuthorizer {
             addAccessPolicy(authorizations, ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, adminUser.getIdentifier(), WRITE_CODE);
         }
 
+        // grant the user write to restricted components
+        addAccessPolicy(authorizations, ResourceType.RestrictedComponents.getValue(), adminUser.getIdentifier(), WRITE_CODE);
+
         // grant the user read/write access to the /tenants resource
         addAccessPolicy(authorizations, ResourceType.Tenant.getValue(), adminUser.getIdentifier(), READ_CODE);
         addAccessPolicy(authorizations, ResourceType.Tenant.getValue(), adminUser.getIdentifier(), WRITE_CODE);

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/RoleAccessPolicy.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/RoleAccessPolicy.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/RoleAccessPolicy.java
index 867423e..16e9c9c 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/RoleAccessPolicy.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/RoleAccessPolicy.java
@@ -72,6 +72,7 @@ public final class RoleAccessPolicy {
         dfmPolicies.add(new RoleAccessPolicy(ResourceType.Controller.getValue(), READ_ACTION));
         dfmPolicies.add(new RoleAccessPolicy(ResourceType.Controller.getValue(), WRITE_ACTION));
         dfmPolicies.add(new RoleAccessPolicy(ResourceType.System.getValue(), READ_ACTION));
+        dfmPolicies.add(new RoleAccessPolicy(ResourceType.RestrictedComponents.getValue(), WRITE_ACTION));
         if (rootGroupId != null) {
             dfmPolicies.add(new RoleAccessPolicy(ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, READ_ACTION));
             dfmPolicies.add(new RoleAccessPolicy(ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, WRITE_ACTION));

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAuthorizerTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAuthorizerTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAuthorizerTest.java
index 7e77e05..c335e19 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAuthorizerTest.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAuthorizerTest.java
@@ -312,7 +312,7 @@ public class FileAuthorizerTest {
 
         // verify user3's policies
         final Map<String,Set<RequestAction>> user3Policies = getResourceActions(policies, user3);
-        assertEquals(5, user3Policies.size());
+        assertEquals(6, user3Policies.size());
 
         assertTrue(user3Policies.containsKey(ResourceType.Flow.getValue()));
         assertEquals(1, user3Policies.get(ResourceType.Flow.getValue()).size());
@@ -502,7 +502,7 @@ public class FileAuthorizerTest {
         assertEquals(adminIdentity, adminUser.getIdentity());
 
         final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
-        assertEquals(11, policies.size());
+        assertEquals(12, policies.size());
 
         final String rootGroupResource = ResourceType.ProcessGroup.getValue() + "/" + ROOT_GROUP_ID;
 
@@ -540,7 +540,7 @@ public class FileAuthorizerTest {
         assertEquals(adminIdentity, adminUser.getIdentity());
 
         final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
-        assertEquals(7, policies.size());
+        assertEquals(8, policies.size());
 
         final String rootGroupResource = ResourceType.ProcessGroup.getValue() + "/" + ROOT_GROUP_ID;
 
@@ -578,7 +578,7 @@ public class FileAuthorizerTest {
         assertEquals(adminIdentity, adminUser.getIdentity());
 
         final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
-        assertEquals(7, policies.size());
+        assertEquals(8, policies.size());
 
         final String rootGroupResource = ResourceType.ProcessGroup.getValue() + "/" + ROOT_GROUP_ID;
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceFactory.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceFactory.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceFactory.java
index 25f5ec3..83c5bb9 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceFactory.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceFactory.java
@@ -142,6 +142,18 @@ public final class ResourceFactory {
         }
     };
 
+    private final static Resource RESTRICTED_COMPONENTS_RESOURCE = new Resource() {
+        @Override
+        public String getIdentifier() {
+            return ResourceType.RestrictedComponents.getValue();
+        }
+
+        @Override
+        public String getName() {
+            return "Restricted Components";
+        }
+    };
+
     private final static Resource TENANT_RESOURCE = new Resource() {
         @Override
         public String getIdentifier() {
@@ -242,6 +254,15 @@ public final class ResourceFactory {
     }
 
     /**
+     * Gets the Resource for accessing restricted components.
+     *
+     * @return The restricted components resource
+     */
+    public static Resource getRestrictedComponentsResource() {
+        return RESTRICTED_COMPONENTS_RESOURCE;
+    }
+
+    /**
      * Gets the Resource for accessing Tenants which includes creating, modifying, and deleting Users and UserGroups.
      *
      * @return The Resource for accessing Tenants

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceType.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceType.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceType.java
index 37fe018..5973f6b 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceType.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceType.java
@@ -37,6 +37,7 @@ public enum ResourceType {
     SiteToSite("/site-to-site"),
     DataTransfer("/data-transfer"),
     System("/system"),
+    RestrictedComponents("/restricted-components"),
     Template("/templates"),
     Tenant("/tenants");
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/RestrictedComponentsAuthorizable.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/RestrictedComponentsAuthorizable.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/RestrictedComponentsAuthorizable.java
new file mode 100644
index 0000000..92a905b
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/RestrictedComponentsAuthorizable.java
@@ -0,0 +1,33 @@
+/*
+ * 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.authorization.resource;
+
+import org.apache.nifi.authorization.Resource;
+
+public class RestrictedComponentsAuthorizable implements Authorizable {
+
+    @Override
+    public Authorizable getParentAuthorizable() {
+        return null;
+    }
+
+    @Override
+    public Resource getResource() {
+        return ResourceFactory.getRestrictedComponentsResource();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ConfiguredComponent.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ConfiguredComponent.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ConfiguredComponent.java
index 7ec3a14..a0a6060 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ConfiguredComponent.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ConfiguredComponent.java
@@ -16,7 +16,14 @@
  */
 package org.apache.nifi.controller;
 
+import org.apache.nifi.authorization.AccessDeniedException;
+import org.apache.nifi.authorization.AuthorizationResult;
+import org.apache.nifi.authorization.AuthorizationResult.Result;
+import org.apache.nifi.authorization.Authorizer;
+import org.apache.nifi.authorization.RequestAction;
 import org.apache.nifi.authorization.resource.ComponentAuthorizable;
+import org.apache.nifi.authorization.resource.RestrictedComponentsAuthorizable;
+import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.components.PropertyDescriptor;
 import org.apache.nifi.components.ValidationResult;
 
@@ -58,4 +65,37 @@ public interface ConfiguredComponent extends ComponentAuthorizable {
      */
     String getCanonicalClassName();
 
+    /**
+     * @return whether or not the underlying implementation is restricted
+     */
+    boolean isRestricted();
+
+    @Override
+    default AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) {
+        // if this is a modification request and the reporting task is restricted ensure the user has elevated privileges. if this
+        // is not a modification request, we just want to use the normal rules
+        if (RequestAction.WRITE.equals(action) && isRestricted()) {
+            final RestrictedComponentsAuthorizable restrictedComponentsAuthorizable = new RestrictedComponentsAuthorizable();
+            final AuthorizationResult result = restrictedComponentsAuthorizable.checkAuthorization(authorizer, RequestAction.WRITE, user, resourceContext);
+            if (Result.Denied.equals(result.getResult())) {
+                return result;
+            }
+        }
+
+        // defer to the base authorization check
+        return ComponentAuthorizable.super.checkAuthorization(authorizer, action, user, resourceContext);
+    }
+
+    @Override
+    default void authorize(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) throws AccessDeniedException {
+        // if this is a modification request and the reporting task is restricted ensure the user has elevated privileges. if this
+        // is not a modification request, we just want to use the normal rules
+        if (RequestAction.WRITE.equals(action) && isRestricted()) {
+            final RestrictedComponentsAuthorizable restrictedComponentsAuthorizable = new RestrictedComponentsAuthorizable();
+            restrictedComponentsAuthorizable.authorize(authorizer, RequestAction.WRITE, user, resourceContext);
+        }
+
+        // defer to the base authorization check
+        ComponentAuthorizable.super.authorize(authorizer, action, user, resourceContext);
+    }
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java
index bfa2129..f94cc8b 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java
@@ -21,6 +21,7 @@ import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.apache.nifi.annotation.behavior.EventDriven;
 import org.apache.nifi.annotation.behavior.InputRequirement;
 import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.behavior.SideEffectFree;
 import org.apache.nifi.annotation.behavior.SupportsBatching;
 import org.apache.nifi.annotation.behavior.TriggerSerially;
@@ -56,8 +57,8 @@ import org.apache.nifi.processor.Processor;
 import org.apache.nifi.processor.Relationship;
 import org.apache.nifi.processor.SimpleProcessLogger;
 import org.apache.nifi.registry.VariableRegistry;
-import org.apache.nifi.scheduling.SchedulingStrategy;
 import org.apache.nifi.scheduling.ExecutionNode;
+import org.apache.nifi.scheduling.SchedulingStrategy;
 import org.apache.nifi.util.FormatUtils;
 import org.apache.nifi.util.NiFiProperties;
 import org.apache.nifi.util.ReflectionUtils;
@@ -236,6 +237,11 @@ public class StandardProcessorNode extends ProcessorNode implements Connectable
         return ResourceFactory.getComponentResource(ResourceType.Processor, getIdentifier(), getName());
     }
 
+    @Override
+    public boolean isRestricted() {
+        return getProcessor().getClass().isAnnotationPresent(Restricted.class);
+    }
+
     /**
      * Provides and opportunity to retain information about this particular
      * processor instance

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/StandardReportingTaskNode.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/StandardReportingTaskNode.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/StandardReportingTaskNode.java
index bb58577..adb2240 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/StandardReportingTaskNode.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/StandardReportingTaskNode.java
@@ -16,6 +16,7 @@
  */
 package org.apache.nifi.controller.reporting;
 
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.authorization.Resource;
 import org.apache.nifi.authorization.resource.Authorizable;
 import org.apache.nifi.authorization.resource.ResourceFactory;
@@ -58,6 +59,11 @@ public class StandardReportingTaskNode extends AbstractReportingTaskNode impleme
     }
 
     @Override
+    public boolean isRestricted() {
+        return getReportingTask().getClass().isAnnotationPresent(Restricted.class);
+    }
+
+    @Override
     public ReportingContext getReportingContext() {
         return new StandardReportingContext(flowController, flowController.getBulletinRepository(), getProperties(), flowController, getReportingTask(), getVariableRegistry());
     }

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java
index c61325a..d4a16b3 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java
@@ -17,6 +17,7 @@
 package org.apache.nifi.controller.service;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.lifecycle.OnDisabled;
 import org.apache.nifi.annotation.lifecycle.OnEnabled;
 import org.apache.nifi.authorization.Resource;
@@ -121,6 +122,11 @@ public class StandardControllerServiceNode extends AbstractConfiguredComponent i
     }
 
     @Override
+    public boolean isRestricted() {
+        return getControllerServiceImplementation().getClass().isAnnotationPresent(Restricted.class);
+    }
+
+    @Override
     public ControllerService getProxiedControllerService() {
         return proxedControllerService;
     }

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java
index 6f3c01b..1d1a828 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java
@@ -34,7 +34,7 @@ public interface AuthorizableLookup {
      * @param id processor id
      * @return authorizable
      */
-    ControllerServiceReferencingComponentAuthorizable getProcessor(String id);
+    ConfigurableComponentAuthorizable getProcessor(String id);
 
     /**
      * Get the authorizable for this Processor. This will create a dummy instance of the
@@ -44,7 +44,7 @@ public interface AuthorizableLookup {
      * @param type processor type
      * @return authorizable
      */
-    ControllerServiceReferencingComponentAuthorizable getProcessorByType(String type);
+    ConfigurableComponentAuthorizable getProcessorByType(String type);
 
     /**
      * Get the authorizable for querying Provenance.
@@ -156,7 +156,7 @@ public interface AuthorizableLookup {
      * @param id controller service id
      * @return authorizable
      */
-    ControllerServiceReferencingComponentAuthorizable getControllerService(String id);
+    ConfigurableComponentAuthorizable getControllerService(String id);
 
     /**
      * Get the authorizable for this Controller Service. This will create a dummy instance of the
@@ -166,7 +166,7 @@ public interface AuthorizableLookup {
      * @param type processor type
      * @return authorizable
      */
-    ControllerServiceReferencingComponentAuthorizable getControllerServiceByType(String type);
+    ConfigurableComponentAuthorizable getControllerServiceByType(String type);
 
     /**
      * Get the authorizable referencing component.
@@ -183,7 +183,7 @@ public interface AuthorizableLookup {
      * @param id reporting task id
      * @return authorizable
      */
-    ControllerServiceReferencingComponentAuthorizable getReportingTask(String id);
+    ConfigurableComponentAuthorizable getReportingTask(String id);
 
     /**
      * Get the authorizable for this Reporting Task. This will create a dummy instance of the
@@ -193,7 +193,7 @@ public interface AuthorizableLookup {
      * @param type processor type
      * @return authorizable
      */
-    ControllerServiceReferencingComponentAuthorizable getReportingTaskByType(String type);
+    ConfigurableComponentAuthorizable getReportingTaskByType(String type);
 
     /**
      * Get the authorizable Template.
@@ -271,4 +271,10 @@ public interface AuthorizableLookup {
      */
     Authorizable getSystem();
 
+    /**
+     * Get the authorizable for accessing restricted components.
+     *
+     * @return authorizable
+     */
+    Authorizable getRestrictedComponents();
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizeControllerServiceReference.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizeControllerServiceReference.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizeControllerServiceReference.java
index 48c782f..a3a4e19 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizeControllerServiceReference.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizeControllerServiceReference.java
@@ -38,7 +38,7 @@ public final class AuthorizeControllerServiceReference {
      * @param authorizer authorizer
      * @param lookup lookup
      */
-    public static void authorizeControllerServiceReferences(final Map<String, String> proposedProperties, final ControllerServiceReferencingComponentAuthorizable authorizable,
+    public static void authorizeControllerServiceReferences(final Map<String, String> proposedProperties, final ConfigurableComponentAuthorizable authorizable,
                                                             final Authorizer authorizer, final AuthorizableLookup lookup) {
 
         // only attempt to authorize if properties are changing

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/ConfigurableComponentAuthorizable.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/ConfigurableComponentAuthorizable.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/ConfigurableComponentAuthorizable.java
new file mode 100644
index 0000000..a06c7a0
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/ConfigurableComponentAuthorizable.java
@@ -0,0 +1,55 @@
+/*
+ * 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.authorization;
+
+import org.apache.nifi.authorization.resource.Authorizable;
+import org.apache.nifi.components.PropertyDescriptor;
+
+/**
+ * Authorizable for a component that references a ControllerService.
+ */
+public interface ConfigurableComponentAuthorizable {
+    /**
+     * Returns the base authorizable for this ControllerServiceReference. Non null
+     *
+     * @return authorizable
+     */
+    Authorizable getAuthorizable();
+
+    /**
+     * Returns whether or not the underlying configurable component is restricted.
+     *
+     * @return whether or not the underlying configurable component is restricted
+     */
+    boolean isRestricted();
+
+    /**
+     * Returns the property descriptor for the specified property.
+     *
+     * @param propertyName property name
+     * @return property descriptor
+     */
+    PropertyDescriptor getPropertyDescriptor(String propertyName);
+
+    /**
+     * Returns the current value of the specified property.
+     *
+     * @param propertyDescriptor property descriptor
+     * @return value
+     */
+    String getValue(PropertyDescriptor propertyDescriptor);
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/7f5eabd6/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/ControllerServiceReferencingComponentAuthorizable.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/ControllerServiceReferencingComponentAuthorizable.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/ControllerServiceReferencingComponentAuthorizable.java
deleted file mode 100644
index abffc94..0000000
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/ControllerServiceReferencingComponentAuthorizable.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.authorization;
-
-import org.apache.nifi.authorization.resource.Authorizable;
-import org.apache.nifi.components.PropertyDescriptor;
-
-/**
- * Authorizable for a component that references a ControllerService.
- */
-public interface ControllerServiceReferencingComponentAuthorizable {
-    /**
-     * Returns the base authorizable for this ControllerServiceReference. Non null
-     *
-     * @return authorizable
-     */
-    Authorizable getAuthorizable();
-
-    /**
-     * Returns the property descriptor for the specified property.
-     *
-     * @param propertyName property name
-     * @return property descriptor
-     */
-    PropertyDescriptor getPropertyDescriptor(String propertyName);
-
-    /**
-     * Returns the current value of the specified property.
-     *
-     * @param propertyDescriptor property descriptor
-     * @return value
-     */
-    String getValue(PropertyDescriptor propertyDescriptor);
-}