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 2017/03/31 16:22:55 UTC

[2/5] nifi-minifi git commit: MINIFI-238 - MiNiFi Initial Command and Control Server Implementation

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-integration-tests/src/test/resources/mocknifi/www/nifi-api/templates/dd737a3e-333e-40df-a0bc-d7e28c8e6843/download
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-integration-tests/src/test/resources/mocknifi/www/nifi-api/templates/dd737a3e-333e-40df-a0bc-d7e28c8e6843/download b/minifi-c2/minifi-c2-integration-tests/src/test/resources/mocknifi/www/nifi-api/templates/dd737a3e-333e-40df-a0bc-d7e28c8e6843/download
new file mode 100644
index 0000000..6b364d0
--- /dev/null
+++ b/minifi-c2/minifi-c2-integration-tests/src/test/resources/mocknifi/www/nifi-api/templates/dd737a3e-333e-40df-a0bc-d7e28c8e6843/download
@@ -0,0 +1,203 @@
+<?xml version="1.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.
+-->
+<template encoding-version="1.0">
+  <description></description>
+  <groupId>8f8eda5e-015a-1000-a9c1-b7e4fe10ae83</groupId>
+  <name>raspi3.v2</name>
+  <snippet>
+    <connections>
+      <id>8f96f2a9-015a-1000-0000-000000000000</id>
+      <parentGroupId>8f8eda5e-015a-1000-0000-000000000000</parentGroupId>
+      <backPressureDataSizeThreshold>1 GB</backPressureDataSizeThreshold>
+      <backPressureObjectThreshold>10000</backPressureObjectThreshold>
+      <destination>
+        <groupId>8f8eda5e-015a-1000-0000-000000000000</groupId>
+        <id>8f96bf68-015a-1000-0000-000000000000</id>
+        <type>PROCESSOR</type>
+      </destination>
+      <flowFileExpiration>0 sec</flowFileExpiration>
+      <labelIndex>1</labelIndex>
+      <name></name>
+      <selectedRelationships>success</selectedRelationships>
+      <source>
+        <groupId>8f8eda5e-015a-1000-0000-000000000000</groupId>
+        <id>8f96e313-015a-1000-0000-000000000000</id>
+        <type>PROCESSOR</type>
+      </source>
+      <zIndex>0</zIndex>
+    </connections>
+    <processors>
+      <id>8f96bf68-015a-1000-0000-000000000000</id>
+      <parentGroupId>8f8eda5e-015a-1000-0000-000000000000</parentGroupId>
+      <position>
+        <x>14.0</x>
+        <y>253.0</y>
+      </position>
+      <config>
+        <bulletinLevel>WARN</bulletinLevel>
+        <comments></comments>
+        <concurrentlySchedulableTaskCount>1</concurrentlySchedulableTaskCount>
+        <descriptors>
+          <entry>
+            <key>Log Level</key>
+            <value>
+              <name>Log Level</name>
+            </value>
+          </entry>
+          <entry>
+            <key>Log Payload</key>
+            <value>
+              <name>Log Payload</name>
+            </value>
+          </entry>
+          <entry>
+            <key>Attributes to Log</key>
+            <value>
+              <name>Attributes to Log</name>
+            </value>
+          </entry>
+          <entry>
+            <key>Attributes to Ignore</key>
+            <value>
+              <name>Attributes to Ignore</name>
+            </value>
+          </entry>
+          <entry>
+            <key>Log prefix</key>
+            <value>
+              <name>Log prefix</name>
+            </value>
+          </entry>
+        </descriptors>
+        <executionNode>ALL</executionNode>
+        <lossTolerant>false</lossTolerant>
+        <penaltyDuration>30 sec</penaltyDuration>
+        <properties>
+          <entry>
+            <key>Log Level</key>
+            <value>info</value>
+          </entry>
+          <entry>
+            <key>Log Payload</key>
+            <value>true</value>
+          </entry>
+          <entry>
+            <key>Attributes to Log</key>
+          </entry>
+          <entry>
+            <key>Attributes to Ignore</key>
+          </entry>
+          <entry>
+            <key>Log prefix</key>
+          </entry>
+        </properties>
+        <runDurationMillis>0</runDurationMillis>
+        <schedulingPeriod>0 sec</schedulingPeriod>
+        <schedulingStrategy>TIMER_DRIVEN</schedulingStrategy>
+        <yieldDuration>1 sec</yieldDuration>
+      </config>
+      <name>LogAttribute</name>
+      <relationships>
+        <autoTerminate>true</autoTerminate>
+        <name>success</name>
+      </relationships>
+      <style></style>
+      <type>org.apache.nifi.processors.standard.LogAttribute</type>
+    </processors>
+    <processors>
+      <id>8f96e313-015a-1000-0000-000000000000</id>
+      <parentGroupId>8f8eda5e-015a-1000-0000-000000000000</parentGroupId>
+      <position>
+        <x>0.0</x>
+        <y>0.0</y>
+      </position>
+      <config>
+        <bulletinLevel>WARN</bulletinLevel>
+        <comments></comments>
+        <concurrentlySchedulableTaskCount>1</concurrentlySchedulableTaskCount>
+        <descriptors>
+          <entry>
+            <key>File Size</key>
+            <value>
+              <name>File Size</name>
+            </value>
+          </entry>
+          <entry>
+            <key>Batch Size</key>
+            <value>
+              <name>Batch Size</name>
+            </value>
+          </entry>
+          <entry>
+            <key>Data Format</key>
+            <value>
+              <name>Data Format</name>
+            </value>
+          </entry>
+          <entry>
+            <key>Unique FlowFiles</key>
+            <value>
+              <name>Unique FlowFiles</name>
+            </value>
+          </entry>
+          <entry>
+            <key>generate-ff-custom-text</key>
+            <value>
+              <name>generate-ff-custom-text</name>
+            </value>
+          </entry>
+        </descriptors>
+        <executionNode>ALL</executionNode>
+        <lossTolerant>false</lossTolerant>
+        <penaltyDuration>30 sec</penaltyDuration>
+        <properties>
+          <entry>
+            <key>File Size</key>
+            <value>0B</value>
+          </entry>
+          <entry>
+            <key>Batch Size</key>
+            <value>1</value>
+          </entry>
+          <entry>
+            <key>Data Format</key>
+            <value>Text</value>
+          </entry>
+          <entry>
+            <key>Unique FlowFiles</key>
+            <value>false</value>
+          </entry>
+          <entry>
+            <key>generate-ff-custom-text</key>
+            <value>abcdefg</value>
+          </entry>
+        </properties>
+        <runDurationMillis>0</runDurationMillis>
+        <schedulingPeriod>0 sec</schedulingPeriod>
+        <schedulingStrategy>TIMER_DRIVEN</schedulingStrategy>
+        <yieldDuration>1 sec</yieldDuration>
+      </config>
+      <name>GenerateFlowFile</name>
+      <relationships>
+        <autoTerminate>false</autoTerminate>
+        <name>success</name>
+      </relationships>
+      <style></style>
+      <type>org.apache.nifi.processors.standard.GenerateFlowFile</type>
+    </processors>
+  </snippet>
+  <timestamp>03/17/2017 13:22:58 EDT</timestamp>
+</template>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-integration-tests/src/test/resources/mocknifi/www/nifi-api/templates/f080ec50-ca32-4b36-8453-5a7145bec4c5/download
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-integration-tests/src/test/resources/mocknifi/www/nifi-api/templates/f080ec50-ca32-4b36-8453-5a7145bec4c5/download b/minifi-c2/minifi-c2-integration-tests/src/test/resources/mocknifi/www/nifi-api/templates/f080ec50-ca32-4b36-8453-5a7145bec4c5/download
new file mode 100644
index 0000000..ad65498
--- /dev/null
+++ b/minifi-c2/minifi-c2-integration-tests/src/test/resources/mocknifi/www/nifi-api/templates/f080ec50-ca32-4b36-8453-5a7145bec4c5/download
@@ -0,0 +1,202 @@
+<?xml version="1.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.
+-->
+<template encoding-version="1.0">
+  <description></description>
+  <groupId>8f8eda5e-015a-1000-a9c1-b7e4fe10ae83</groupId>
+  <name>raspi3.v1</name>
+  <snippet>
+    <connections>
+      <id>8f96f2a9-015a-1000-0000-000000000000</id>
+      <parentGroupId>8f8eda5e-015a-1000-0000-000000000000</parentGroupId>
+      <backPressureDataSizeThreshold>1 GB</backPressureDataSizeThreshold>
+      <backPressureObjectThreshold>10000</backPressureObjectThreshold>
+      <destination>
+        <groupId>8f8eda5e-015a-1000-0000-000000000000</groupId>
+        <id>8f96bf68-015a-1000-0000-000000000000</id>
+        <type>PROCESSOR</type>
+      </destination>
+      <flowFileExpiration>0 sec</flowFileExpiration>
+      <labelIndex>1</labelIndex>
+      <name></name>
+      <selectedRelationships>success</selectedRelationships>
+      <source>
+        <groupId>8f8eda5e-015a-1000-0000-000000000000</groupId>
+        <id>8f96e313-015a-1000-0000-000000000000</id>
+        <type>PROCESSOR</type>
+      </source>
+      <zIndex>0</zIndex>
+    </connections>
+    <processors>
+      <id>8f96bf68-015a-1000-0000-000000000000</id>
+      <parentGroupId>8f8eda5e-015a-1000-0000-000000000000</parentGroupId>
+      <position>
+        <x>14.0</x>
+        <y>253.0</y>
+      </position>
+      <config>
+        <bulletinLevel>WARN</bulletinLevel>
+        <comments></comments>
+        <concurrentlySchedulableTaskCount>1</concurrentlySchedulableTaskCount>
+        <descriptors>
+          <entry>
+            <key>Log prefix</key>
+            <value>
+              <name>Log prefix</name>
+            </value>
+          </entry>
+          <entry>
+            <key>Log Level</key>
+            <value>
+              <name>Log Level</name>
+            </value>
+          </entry>
+          <entry>
+            <key>Attributes to Ignore</key>
+            <value>
+              <name>Attributes to Ignore</name>
+            </value>
+          </entry>
+          <entry>
+            <key>Attributes to Log</key>
+            <value>
+              <name>Attributes to Log</name>
+            </value>
+          </entry>
+          <entry>
+            <key>Log Payload</key>
+            <value>
+              <name>Log Payload</name>
+            </value>
+          </entry>
+        </descriptors>
+        <executionNode>ALL</executionNode>
+        <lossTolerant>false</lossTolerant>
+        <penaltyDuration>30 sec</penaltyDuration>
+        <properties>
+          <entry>
+            <key>Log prefix</key>
+          </entry>
+          <entry>
+            <key>Log Level</key>
+            <value>info</value>
+          </entry>
+          <entry>
+            <key>Attributes to Ignore</key>
+          </entry>
+          <entry>
+            <key>Attributes to Log</key>
+          </entry>
+          <entry>
+            <key>Log Payload</key>
+            <value>true</value>
+          </entry>
+        </properties>
+        <runDurationMillis>0</runDurationMillis>
+        <schedulingPeriod>0 sec</schedulingPeriod>
+        <schedulingStrategy>TIMER_DRIVEN</schedulingStrategy>
+        <yieldDuration>1 sec</yieldDuration>
+      </config>
+      <name>LogAttribute</name>
+      <relationships>
+        <autoTerminate>true</autoTerminate>
+        <name>success</name>
+      </relationships>
+      <style></style>
+      <type>org.apache.nifi.processors.standard.LogAttribute</type>
+    </processors>
+    <processors>
+      <id>8f96e313-015a-1000-0000-000000000000</id>
+      <parentGroupId>8f8eda5e-015a-1000-0000-000000000000</parentGroupId>
+      <position>
+        <x>0.0</x>
+        <y>0.0</y>
+      </position>
+      <config>
+        <bulletinLevel>WARN</bulletinLevel>
+        <comments></comments>
+        <concurrentlySchedulableTaskCount>1</concurrentlySchedulableTaskCount>
+        <descriptors>
+          <entry>
+            <key>File Size</key>
+            <value>
+              <name>File Size</name>
+            </value>
+          </entry>
+          <entry>
+            <key>generate-ff-custom-text</key>
+            <value>
+              <name>generate-ff-custom-text</name>
+            </value>
+          </entry>
+          <entry>
+            <key>Batch Size</key>
+            <value>
+              <name>Batch Size</name>
+            </value>
+          </entry>
+          <entry>
+            <key>Unique FlowFiles</key>
+            <value>
+              <name>Unique FlowFiles</name>
+            </value>
+          </entry>
+          <entry>
+            <key>Data Format</key>
+            <value>
+              <name>Data Format</name>
+            </value>
+          </entry>
+        </descriptors>
+        <executionNode>ALL</executionNode>
+        <lossTolerant>false</lossTolerant>
+        <penaltyDuration>30 sec</penaltyDuration>
+        <properties>
+          <entry>
+            <key>File Size</key>
+            <value>0B</value>
+          </entry>
+          <entry>
+            <key>generate-ff-custom-text</key>
+          </entry>
+          <entry>
+            <key>Batch Size</key>
+            <value>1</value>
+          </entry>
+          <entry>
+            <key>Unique FlowFiles</key>
+            <value>false</value>
+          </entry>
+          <entry>
+            <key>Data Format</key>
+            <value>Text</value>
+          </entry>
+        </properties>
+        <runDurationMillis>0</runDurationMillis>
+        <schedulingPeriod>0 sec</schedulingPeriod>
+        <schedulingStrategy>TIMER_DRIVEN</schedulingStrategy>
+        <yieldDuration>1 sec</yieldDuration>
+      </config>
+      <name>GenerateFlowFile</name>
+      <relationships>
+        <autoTerminate>false</autoTerminate>
+        <name>success</name>
+      </relationships>
+      <style></style>
+      <type>org.apache.nifi.processors.standard.GenerateFlowFile</type>
+    </processors>
+  </snippet>
+  <timestamp>03/07/2017 11:13:03 EST</timestamp>
+</template>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-integration-tests/src/test/resources/overlay.properties
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-integration-tests/src/test/resources/overlay.properties b/minifi-c2/minifi-c2-integration-tests/src/test/resources/overlay.properties
new file mode 100644
index 0000000..b1312a0
--- /dev/null
+++ b/minifi-c2/minifi-c2-integration-tests/src/test/resources/overlay.properties
@@ -0,0 +1,16 @@
+#
+# 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.
+#

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-integration-tests/src/test/resources/squid/squid.conf
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-integration-tests/src/test/resources/squid/squid.conf b/minifi-c2/minifi-c2-integration-tests/src/test/resources/squid/squid.conf
new file mode 100644
index 0000000..90a5248
--- /dev/null
+++ b/minifi-c2/minifi-c2-integration-tests/src/test/resources/squid/squid.conf
@@ -0,0 +1,19 @@
+# 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.
+
+http_access allow all
+
+# Choose the port you want. Below we set it to default 3128.
+http_port 3128
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-jetty/pom.xml
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-jetty/pom.xml b/minifi-c2/minifi-c2-jetty/pom.xml
new file mode 100644
index 0000000..df24c62
--- /dev/null
+++ b/minifi-c2/minifi-c2-jetty/pom.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>minifi-c2</artifactId>
+        <groupId>org.apache.nifi.minifi</groupId>
+        <version>0.2.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>minifi-c2-jetty</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.nifi.minifi</groupId>
+            <artifactId>minifi-c2-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-server</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-webapp</artifactId>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-jetty/src/main/java/org/apache/nifi/minifi/c2/jetty/JettyServer.java
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-jetty/src/main/java/org/apache/nifi/minifi/c2/jetty/JettyServer.java b/minifi-c2/minifi-c2-jetty/src/main/java/org/apache/nifi/minifi/c2/jetty/JettyServer.java
new file mode 100644
index 0000000..5c8b1f8
--- /dev/null
+++ b/minifi-c2/minifi-c2-jetty/src/main/java/org/apache/nifi/minifi/c2/jetty/JettyServer.java
@@ -0,0 +1,142 @@
+/*
+ * 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.minifi.c2.jetty;
+
+import org.apache.nifi.minifi.c2.api.properties.C2Properties;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.SecureRequestCustomizer;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.SslConnectionFactory;
+import org.eclipse.jetty.server.handler.HandlerCollection;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.eclipse.jetty.webapp.WebAppClassLoader;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class JettyServer {
+    private static final Logger logger = LoggerFactory.getLogger(JettyServer.class);
+    private static String C2_SERVER_HOME = System.getenv("C2_SERVER_HOME");
+    private static final String WEB_DEFAULTS_XML = "webdefault.xml";
+
+    public static void main(String[] args) throws Exception {
+        C2Properties properties = C2Properties.getInstance();
+
+        final HandlerCollection handlers = new HandlerCollection();
+        for (Path path : Files.list(Paths.get(C2_SERVER_HOME, "webapps")).collect(Collectors.toList())) {
+             handlers.addHandler(loadWar(path.toFile(), "/c2", JettyServer.class.getClassLoader()));
+        }
+
+        Server server;
+        int port = Integer.parseInt(properties.getProperty("minifi.c2.server.port", "10080"));
+        SslContextFactory sslContextFactory = properties.getSslContextFactory();
+        if (sslContextFactory == null) {
+            server = new Server(port);
+        } else {
+            HttpConfiguration config = new HttpConfiguration();
+            config.setSecureScheme("https");
+            config.setSecurePort(port);
+            config.addCustomizer(new SecureRequestCustomizer());
+
+            server = new Server();
+
+            ServerConnector serverConnector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, "http/1.1"), new HttpConnectionFactory(config));
+            serverConnector.setPort(port);
+
+            server.addConnector(serverConnector);
+        }
+
+        server.setHandler(handlers);
+        server.start();
+
+        // ensure everything started successfully
+        for (Handler handler : server.getChildHandlers()) {
+            // see if the handler is a web app
+            if (handler instanceof WebAppContext) {
+                WebAppContext context = (WebAppContext) handler;
+
+                // see if this webapp had any exceptions that would
+                // cause it to be unavailable
+                if (context.getUnavailableException() != null) {
+
+                    System.err.println("Failed to start web server: " + context.getUnavailableException().getMessage());
+                    System.err.println("Shutting down...");
+                    logger.warn("Failed to start web server... shutting down.", context.getUnavailableException());
+                    server.stop();
+                    System.exit(1);
+                }
+            }
+        }
+
+        server.dumpStdErr();
+        server.join();
+    }
+
+    private static WebAppContext loadWar(final File warFile, final String contextPath, final ClassLoader parentClassLoader) throws IOException {
+        final WebAppContext webappContext = new WebAppContext(warFile.getPath(), contextPath);
+        webappContext.setContextPath(contextPath);
+        webappContext.setDisplayName(contextPath);
+
+        // instruction jetty to examine these jars for tlds, web-fragments, etc
+        webappContext.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", ".*/[^/]*servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\\\.jar$|.*/[^/]*taglibs.*\\.jar$" );
+
+        // remove slf4j server class to allow WAR files to have slf4j dependencies in WEB-INF/lib
+        List<String> serverClasses = new ArrayList<>(Arrays.asList(webappContext.getServerClasses()));
+        serverClasses.remove("org.slf4j.");
+        webappContext.setServerClasses(serverClasses.toArray(new String[0]));
+        webappContext.setDefaultsDescriptor(WEB_DEFAULTS_XML);
+
+        // get the temp directory for this webapp
+        File tempDir = Paths.get(C2_SERVER_HOME, "tmp", warFile.getName()).toFile();
+        if (tempDir.exists() && !tempDir.isDirectory()) {
+            throw new RuntimeException(tempDir.getAbsolutePath() + " is not a directory");
+        } else if (!tempDir.exists()) {
+            final boolean made = tempDir.mkdirs();
+            if (!made) {
+                throw new RuntimeException(tempDir.getAbsolutePath() + " could not be created");
+            }
+        }
+        if (!(tempDir.canRead() && tempDir.canWrite())) {
+            throw new RuntimeException(tempDir.getAbsolutePath() + " directory does not have read/write privilege");
+        }
+
+        // configure the temp dir
+        webappContext.setTempDirectory(tempDir);
+
+        // configure the max form size (3x the default)
+        webappContext.setMaxFormContentSize(600000);
+
+        webappContext.setClassLoader(new WebAppClassLoader(parentClassLoader, webappContext));
+
+        logger.info("Loading WAR: " + warFile.getAbsolutePath() + " with context path set to " + contextPath);
+        return webappContext;
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-provider/minifi-c2-provider-cache/pom.xml
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-provider/minifi-c2-provider-cache/pom.xml b/minifi-c2/minifi-c2-provider/minifi-c2-provider-cache/pom.xml
new file mode 100644
index 0000000..76e082e
--- /dev/null
+++ b/minifi-c2/minifi-c2-provider/minifi-c2-provider-cache/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>minifi-c2-provider</artifactId>
+        <groupId>org.apache.nifi.minifi</groupId>
+        <version>0.2.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>minifi-c2-provider-cache</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.nifi.minifi</groupId>
+            <artifactId>minifi-c2-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-provider/minifi-c2-provider-cache/src/main/java/org/apache/nifi/minifi/c2/provider/cache/CacheConfigurationProvider.java
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-provider/minifi-c2-provider-cache/src/main/java/org/apache/nifi/minifi/c2/provider/cache/CacheConfigurationProvider.java b/minifi-c2/minifi-c2-provider/minifi-c2-provider-cache/src/main/java/org/apache/nifi/minifi/c2/provider/cache/CacheConfigurationProvider.java
new file mode 100644
index 0000000..b0864ac
--- /dev/null
+++ b/minifi-c2/minifi-c2-provider/minifi-c2-provider-cache/src/main/java/org/apache/nifi/minifi/c2/provider/cache/CacheConfigurationProvider.java
@@ -0,0 +1,46 @@
+/*
+ * 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.minifi.c2.provider.cache;
+
+import org.apache.nifi.minifi.c2.api.Configuration;
+import org.apache.nifi.minifi.c2.api.ConfigurationProvider;
+import org.apache.nifi.minifi.c2.api.ConfigurationProviderException;
+import org.apache.nifi.minifi.c2.api.cache.ConfigurationCache;
+
+import java.util.List;
+import java.util.Map;
+
+public class CacheConfigurationProvider implements ConfigurationProvider {
+    private final String contentType;
+    private final ConfigurationCache configurationCache;
+
+    public CacheConfigurationProvider(String contentType, ConfigurationCache configurationCache) {
+        this.contentType = contentType;
+        this.configurationCache = configurationCache;
+    }
+
+    @Override
+    public String getContentType() {
+        return contentType;
+    }
+
+    @Override
+    public Configuration getConfiguration(Integer version, Map<String, List<String>> parameters) throws ConfigurationProviderException {
+        return configurationCache.getCacheFileInfo(parameters).getConfiguration(version);
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-provider/minifi-c2-provider-cache/src/test/java/org/apache/nifi/minifi/c2/provider/cache/CacheConfigurationProviderTest.java
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-provider/minifi-c2-provider-cache/src/test/java/org/apache/nifi/minifi/c2/provider/cache/CacheConfigurationProviderTest.java b/minifi-c2/minifi-c2-provider/minifi-c2-provider-cache/src/test/java/org/apache/nifi/minifi/c2/provider/cache/CacheConfigurationProviderTest.java
new file mode 100644
index 0000000..d038194
--- /dev/null
+++ b/minifi-c2/minifi-c2-provider/minifi-c2-provider-cache/src/test/java/org/apache/nifi/minifi/c2/provider/cache/CacheConfigurationProviderTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.minifi.c2.provider.cache;
+
+import org.apache.nifi.minifi.c2.api.ConfigurationProviderException;
+import org.apache.nifi.minifi.c2.api.cache.ConfigurationCache;
+import org.apache.nifi.minifi.c2.api.cache.ConfigurationCacheFileInfo;
+import org.apache.nifi.minifi.c2.api.cache.WriteableConfiguration;
+import org.apache.nifi.minifi.c2.provider.cache.CacheConfigurationProvider;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class CacheConfigurationProviderTest {
+    public static final String TEST_CONTENT_TYPE = "test/contenttype";
+
+    private CacheConfigurationProvider cacheConfigurationProvider;
+    private ConfigurationCache configConfigurationCache;
+
+    @Before
+    public void setup() {
+        configConfigurationCache = mock(ConfigurationCache.class);
+        cacheConfigurationProvider = new CacheConfigurationProvider(TEST_CONTENT_TYPE, configConfigurationCache);
+    }
+
+    @Test
+    public void testContentType() {
+        assertEquals(TEST_CONTENT_TYPE, cacheConfigurationProvider.getContentType());
+    }
+
+    @Test
+    public void testGetConfiguration() throws ConfigurationProviderException {
+        int version = 99;
+
+        Map<String, List<String>> parameters = mock(Map.class);
+        ConfigurationCacheFileInfo configurationCacheFileInfo = mock(ConfigurationCacheFileInfo.class);
+        WriteableConfiguration configuration = mock(WriteableConfiguration.class);
+
+        when(configConfigurationCache.getCacheFileInfo(parameters)).thenReturn(configurationCacheFileInfo);
+        when(configurationCacheFileInfo.getConfiguration(version)).thenReturn(configuration);
+
+        assertEquals(configuration, cacheConfigurationProvider.getConfiguration(version, parameters));
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/pom.xml
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/pom.xml b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/pom.xml
new file mode 100644
index 0000000..8595246
--- /dev/null
+++ b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/pom.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>minifi-c2-provider</artifactId>
+        <groupId>org.apache.nifi.minifi</groupId>
+        <version>0.2.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>minifi-c2-provider-nifi-rest</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.nifi.minifi</groupId>
+            <artifactId>minifi-c2-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+            <version>2.8.7</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-util</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi.minifi</groupId>
+            <artifactId>minifi-toolkit-configuration</artifactId>
+            <version>${project.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-log4j12</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.rat</groupId>
+                <artifactId>apache-rat-plugin</artifactId>
+                <configuration>
+                    <excludes combine.children="append">
+                        <exclude>src/test/resources/noTemplates.json</exclude>
+                        <exclude>src/test/resources/oneTemplate.json</exclude>
+                        <exclude>src/test/resources/twoTemplates.json</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/main/java/org/apache/nifi/minifi/c2/provider/nifi/rest/NiFiRestConfigurationProvider.java
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/main/java/org/apache/nifi/minifi/c2/provider/nifi/rest/NiFiRestConfigurationProvider.java b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/main/java/org/apache/nifi/minifi/c2/provider/nifi/rest/NiFiRestConfigurationProvider.java
new file mode 100644
index 0000000..77175d7
--- /dev/null
+++ b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/main/java/org/apache/nifi/minifi/c2/provider/nifi/rest/NiFiRestConfigurationProvider.java
@@ -0,0 +1,149 @@
+/*
+ * 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.minifi.c2.provider.nifi.rest;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import org.apache.nifi.minifi.c2.api.Configuration;
+import org.apache.nifi.minifi.c2.api.ConfigurationProvider;
+import org.apache.nifi.minifi.c2.api.ConfigurationProviderException;
+import org.apache.nifi.minifi.c2.api.InvalidParameterException;
+import org.apache.nifi.minifi.c2.api.cache.ConfigurationCache;
+import org.apache.nifi.minifi.c2.api.cache.ConfigurationCacheFileInfo;
+import org.apache.nifi.minifi.c2.api.cache.WriteableConfiguration;
+import org.apache.nifi.minifi.c2.api.util.Pair;
+import org.apache.nifi.minifi.commons.schema.ConfigSchema;
+import org.apache.nifi.minifi.commons.schema.serialization.SchemaSaver;
+import org.apache.nifi.minifi.toolkit.configuration.ConfigMain;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.xml.bind.JAXBException;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.security.GeneralSecurityException;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+public class NiFiRestConfigurationProvider implements ConfigurationProvider {
+    public static final String CONTENT_TYPE = "text/yml";
+    private static final Logger logger = LoggerFactory.getLogger(NiFiRestConfigurationProvider.class);
+    private final JsonFactory jsonFactory = new JsonFactory();
+    private final ConfigurationCache configurationCache;
+    private final NiFiRestConnector niFiRestConnector;
+
+    public NiFiRestConfigurationProvider(ConfigurationCache configurationCache, String nifiUrl) throws InvalidParameterException, GeneralSecurityException, IOException {
+        this(configurationCache, new NiFiRestConnector(nifiUrl));
+    }
+
+    public NiFiRestConfigurationProvider(ConfigurationCache configurationCache, NiFiRestConnector niFiRestConnector) {
+        this.configurationCache = configurationCache;
+        this.niFiRestConnector = niFiRestConnector;
+    }
+
+    @Override
+    public String getContentType() {
+        return CONTENT_TYPE;
+    }
+
+    @Override
+    public Configuration getConfiguration(Integer version, Map<String, List<String>> parameters) throws ConfigurationProviderException {
+        ConfigurationCacheFileInfo configurationCacheFileInfo = configurationCache.getCacheFileInfo(parameters);
+        String id = null;
+        if (version == null) {
+            Pair<String, Integer> maxIdAndVersion = getMaxIdAndVersion(configurationCacheFileInfo);
+            id = maxIdAndVersion.getFirst();
+            version = maxIdAndVersion.getSecond();
+        }
+        WriteableConfiguration configuration = configurationCacheFileInfo.getConfiguration(version);
+        if (configuration.exists()) {
+            if (logger.isDebugEnabled()) {
+                logger.debug("Configuration " + configuration + " exists and can be served from configurationCache.");
+            }
+        } else {
+            if (logger.isDebugEnabled()) {
+                logger.debug("Configuration " + configuration + " doesn't exist, will need to download and convert template.");
+            }
+            if (id == null) {
+                try {
+                    String filename = configuration.getName();
+                    Pair<Stream<Pair<String, String>>, Closeable> streamCloseablePair = getIdAndFilenameStream();
+                    try {
+                        id = streamCloseablePair.getFirst().filter(p -> filename.equals(p.getSecond())).map(Pair::getFirst).findFirst()
+                                .orElseThrow(() -> new InvalidParameterException("Unable to find template named " + filename));
+                    } finally {
+                        streamCloseablePair.getSecond().close();
+                    }
+                } catch (IOException|TemplatesIteratorException e) {
+                    throw new ConfigurationProviderException("Unable to retrieve template list", e);
+                }
+            }
+
+            HttpURLConnection urlConnection = niFiRestConnector.get("/templates/" + id + "/download");
+
+            try (InputStream inputStream = urlConnection.getInputStream()){
+                ConfigSchema configSchema = ConfigMain.transformTemplateToSchema(inputStream);
+                SchemaSaver.saveConfigSchema(configSchema, configuration.getOutputStream());
+            } catch (IOException e) {
+                throw new ConfigurationProviderException("Unable to download template from url " + urlConnection.getURL(), e);
+            } catch (JAXBException e) {
+                throw new ConfigurationProviderException("Unable to convert template to yaml", e);
+            } finally {
+                urlConnection.disconnect();
+            }
+        }
+        return configuration;
+    }
+
+    private Pair<Stream<Pair<String, String>>, Closeable> getIdAndFilenameStream() throws ConfigurationProviderException, IOException {
+        TemplatesIterator templatesIterator = new TemplatesIterator(niFiRestConnector, jsonFactory);
+        return new Pair<>(StreamSupport.stream(Spliterators.spliteratorUnknownSize(templatesIterator, Spliterator.ORDERED), false), templatesIterator);
+    }
+
+    private Pair<Stream<Pair<String, Integer>>, Closeable> getIdAndVersionStream(ConfigurationCacheFileInfo configurationCacheFileInfo) throws ConfigurationProviderException, IOException {
+        Pair<Stream<Pair<String, String>>, Closeable> streamCloseablePair = getIdAndFilenameStream();
+        return new Pair<>(streamCloseablePair.getFirst().map(p -> {
+            Integer version = configurationCacheFileInfo.getVersionIfMatch(p.getSecond());
+            if (version == null) {
+                return null;
+            }
+            return new Pair<>(p.getFirst(), version);
+        }).filter(Objects::nonNull), streamCloseablePair.getSecond());
+    }
+
+    private Pair<String, Integer> getMaxIdAndVersion(ConfigurationCacheFileInfo configurationCacheFileInfo) throws ConfigurationProviderException {
+        try {
+            Pair<Stream<Pair<String, Integer>>, Closeable> streamCloseablePair = getIdAndVersionStream(configurationCacheFileInfo);
+            try {
+                return streamCloseablePair.getFirst().sorted(Comparator.comparing(p -> ((Pair<String, Integer>) p).getSecond()).reversed()).findFirst()
+                        .orElseThrow(() -> new ConfigurationProviderException("Didn't find any templates that matched " + configurationCacheFileInfo + ".v[0-9]+"));
+            } finally {
+                streamCloseablePair.getSecond().close();
+            }
+        } catch (IOException|TemplatesIteratorException e) {
+            throw new ConfigurationProviderException("Unable to retrieve template list", e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/main/java/org/apache/nifi/minifi/c2/provider/nifi/rest/NiFiRestConnector.java
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/main/java/org/apache/nifi/minifi/c2/provider/nifi/rest/NiFiRestConnector.java b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/main/java/org/apache/nifi/minifi/c2/provider/nifi/rest/NiFiRestConnector.java
new file mode 100644
index 0000000..9a0befc
--- /dev/null
+++ b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/main/java/org/apache/nifi/minifi/c2/provider/nifi/rest/NiFiRestConnector.java
@@ -0,0 +1,80 @@
+/*
+ * 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.minifi.c2.provider.nifi.rest;
+
+import org.apache.nifi.minifi.c2.api.ConfigurationProviderException;
+import org.apache.nifi.minifi.c2.api.InvalidParameterException;
+import org.apache.nifi.minifi.c2.api.properties.C2Properties;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+
+public class NiFiRestConnector {
+    private static final Logger logger = LoggerFactory.getLogger(NiFiRestConnector.class);
+
+    private final String nifiApiUrl;
+    private final SslContextFactory sslContextFactory;
+
+    public NiFiRestConnector(String nifiApiUrl) throws InvalidParameterException, GeneralSecurityException, IOException {
+        if (nifiApiUrl.startsWith("https:")) {
+            sslContextFactory = C2Properties.getInstance().getSslContextFactory();
+            if (sslContextFactory == null) {
+                throw new InvalidParameterException("Need sslContextFactory to connect to https NiFi endpoint (" + nifiApiUrl + ")");
+            }
+        } else {
+            sslContextFactory = null;
+        }
+        this.nifiApiUrl = nifiApiUrl;
+    }
+
+    protected HttpURLConnection get(String endpointPath) throws ConfigurationProviderException {
+        String endpointUrl = nifiApiUrl + endpointPath;
+        if (logger.isDebugEnabled()) {
+            logger.debug("Connecting to NiFi endpoint: " + endpointUrl);
+        }
+        URL url;
+        try {
+            url = new URL(endpointUrl);
+        } catch (MalformedURLException e) {
+            throw new ConfigurationProviderException("Malformed url " + endpointUrl, e);
+        }
+
+        try {
+            if (sslContextFactory == null) {
+                return (HttpURLConnection) url.openConnection();
+            } else {
+                HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection();
+                SSLContext sslContext = sslContextFactory.getSslContext();
+                SSLSocketFactory socketFactory = sslContext.getSocketFactory();
+                httpsURLConnection.setSSLSocketFactory(socketFactory);
+                return httpsURLConnection;
+            }
+        } catch (IOException e) {
+            throw new ConfigurationProviderException("Unable to connect to " + url, e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/main/java/org/apache/nifi/minifi/c2/provider/nifi/rest/TemplatesIterator.java
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/main/java/org/apache/nifi/minifi/c2/provider/nifi/rest/TemplatesIterator.java b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/main/java/org/apache/nifi/minifi/c2/provider/nifi/rest/TemplatesIterator.java
new file mode 100644
index 0000000..afe6c6e
--- /dev/null
+++ b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/main/java/org/apache/nifi/minifi/c2/provider/nifi/rest/TemplatesIterator.java
@@ -0,0 +1,115 @@
+/*
+ * 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.minifi.c2.provider.nifi.rest;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import org.apache.nifi.minifi.c2.api.ConfigurationProviderException;
+import org.apache.nifi.minifi.c2.api.util.Pair;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+public class TemplatesIterator implements Iterator<Pair<String, String>>, Closeable {
+    public static final String FLOW_TEMPLATES = "/flow/templates";
+
+    private final HttpURLConnection urlConnection;
+    private final InputStream inputStream;
+    private final JsonParser parser;
+    private Pair<String, String> next;
+
+    public TemplatesIterator(NiFiRestConnector niFiRestConnector, JsonFactory jsonFactory) throws ConfigurationProviderException, IOException {
+        urlConnection = niFiRestConnector.get(FLOW_TEMPLATES);
+        inputStream = urlConnection.getInputStream();
+        parser = jsonFactory.createParser(inputStream);
+        while (parser.nextToken() != JsonToken.END_OBJECT) {
+            if ("templates".equals(parser.getCurrentName())) {
+                break;
+            }
+        }
+        next = getNext();
+    }
+
+    private Pair<String, String> getNext() throws IOException {
+        while (parser.nextToken() != JsonToken.END_ARRAY) {
+            if ("template".equals(parser.getCurrentName())) {
+                String id = null;
+                String name = null;
+                while (parser.nextToken() != JsonToken.END_OBJECT) {
+                    String currentName = parser.getCurrentName();
+                    if ("id".equals(currentName)) {
+                        parser.nextToken();
+                        id = parser.getText();
+                    } else if ("name".equals(currentName)) {
+                        parser.nextToken();
+                        name = parser.getText();
+                    }
+                }
+                return new Pair<>(id, name);
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public boolean hasNext() {
+        return next != null;
+    }
+
+    @Override
+    public Pair<String, String> next() {
+        if (next == null) {
+            throw new NoSuchElementException();
+        }
+        try {
+            return next;
+        } finally {
+            try {
+                next = getNext();
+            } catch (IOException e) {
+                throw new TemplatesIteratorException(e);
+            }
+        }
+    }
+
+    @Override
+    public void close() throws IOException {
+        if (parser != null) {
+            try {
+                parser.close();
+            } catch (IOException e) {
+                //Ignore
+            }
+        }
+        if (inputStream != null) {
+            try {
+                inputStream.close();
+            } catch (IOException e) {
+                //Ignore
+            }
+        }
+        if (urlConnection != null) {
+            urlConnection.disconnect();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/main/java/org/apache/nifi/minifi/c2/provider/nifi/rest/TemplatesIteratorException.java
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/main/java/org/apache/nifi/minifi/c2/provider/nifi/rest/TemplatesIteratorException.java b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/main/java/org/apache/nifi/minifi/c2/provider/nifi/rest/TemplatesIteratorException.java
new file mode 100644
index 0000000..af22474
--- /dev/null
+++ b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/main/java/org/apache/nifi/minifi/c2/provider/nifi/rest/TemplatesIteratorException.java
@@ -0,0 +1,31 @@
+/*
+ * 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.minifi.c2.provider.nifi.rest;
+
+import java.io.IOException;
+
+public class TemplatesIteratorException extends RuntimeException {
+    public TemplatesIteratorException(IOException cause) {
+        super(cause);
+    }
+
+    @Override
+    public synchronized IOException getCause() {
+        return (IOException) super.getCause();
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/java/org/apache/nifi/minifi/c2/provider/nifi/rest/NiFiRestConfigurationProviderTest.java
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/java/org/apache/nifi/minifi/c2/provider/nifi/rest/NiFiRestConfigurationProviderTest.java b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/java/org/apache/nifi/minifi/c2/provider/nifi/rest/NiFiRestConfigurationProviderTest.java
new file mode 100644
index 0000000..2cb3a8d
--- /dev/null
+++ b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/java/org/apache/nifi/minifi/c2/provider/nifi/rest/NiFiRestConfigurationProviderTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.minifi.c2.provider.nifi.rest;
+
+import org.apache.nifi.minifi.c2.api.cache.ConfigurationCache;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Comparator;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+
+public class NiFiRestConfigurationProviderTest {
+    private ConfigurationCache configConfigurationCache;
+    private NiFiRestConnector niFiRestConnector;
+    private NiFiRestConfigurationProvider niFiRestConfigurationProvider;
+    private Path cachePath;
+
+    @Before
+    public void setup() throws IOException {
+        configConfigurationCache = mock(ConfigurationCache.class);
+        niFiRestConnector = mock(NiFiRestConnector.class);
+        niFiRestConfigurationProvider = new NiFiRestConfigurationProvider(configConfigurationCache, niFiRestConnector);
+        cachePath = Files.createTempDirectory(NiFiRestConfigurationProviderTest.class.getCanonicalName());
+    }
+
+    @After
+    public void teardown() throws IOException {
+        Files.walk(cachePath)
+                .sorted(Comparator.reverseOrder())
+                .forEach(p -> {
+                    try {
+                        Files.deleteIfExists(p);
+                    } catch (IOException e) {
+                        p.toFile().deleteOnExit();
+                    }
+                });
+    }
+
+    @Test
+    public void testContentType() {
+        assertEquals(NiFiRestConfigurationProvider.CONTENT_TYPE, niFiRestConfigurationProvider.getContentType());
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/java/org/apache/nifi/minifi/c2/provider/nifi/rest/TemplatesIteratorExceptionTest.java
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/java/org/apache/nifi/minifi/c2/provider/nifi/rest/TemplatesIteratorExceptionTest.java b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/java/org/apache/nifi/minifi/c2/provider/nifi/rest/TemplatesIteratorExceptionTest.java
new file mode 100644
index 0000000..3be3445
--- /dev/null
+++ b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/java/org/apache/nifi/minifi/c2/provider/nifi/rest/TemplatesIteratorExceptionTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.minifi.c2.provider.nifi.rest;
+
+import org.apache.nifi.minifi.c2.provider.nifi.rest.TemplatesIteratorException;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+
+public class TemplatesIteratorExceptionTest {
+    @Test
+    public void testCauseConstructor() {
+        IOException ioException = mock(IOException.class);
+        assertEquals(ioException, new TemplatesIteratorException(ioException).getCause());
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/java/org/apache/nifi/minifi/c2/provider/nifi/rest/TemplatesIteratorTest.java
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/java/org/apache/nifi/minifi/c2/provider/nifi/rest/TemplatesIteratorTest.java b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/java/org/apache/nifi/minifi/c2/provider/nifi/rest/TemplatesIteratorTest.java
new file mode 100644
index 0000000..ca20e4a
--- /dev/null
+++ b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/java/org/apache/nifi/minifi/c2/provider/nifi/rest/TemplatesIteratorTest.java
@@ -0,0 +1,108 @@
+/*
+ * 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.minifi.c2.provider.nifi.rest;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.google.common.collect.Lists;
+import org.apache.nifi.minifi.c2.api.ConfigurationProviderException;
+import org.apache.nifi.minifi.c2.api.util.Pair;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class TemplatesIteratorTest {
+    private JsonFactory jsonFactory;
+    private HttpURLConnection httpURLConnection;
+    private NiFiRestConnector niFiRestConnector;
+
+    @Before
+    public void setup() throws ConfigurationProviderException {
+        jsonFactory = new JsonFactory();
+        httpURLConnection = mock(HttpURLConnection.class);
+        niFiRestConnector = mock(NiFiRestConnector.class);
+        when(niFiRestConnector.get(TemplatesIterator.FLOW_TEMPLATES)).thenReturn(httpURLConnection);
+    }
+
+    @Test(expected = NoSuchElementException.class)
+    public void testIteratorNoSuchElementException() throws ConfigurationProviderException, IOException {
+        when(httpURLConnection.getInputStream()).thenReturn(TemplatesIteratorTest.class.getClassLoader().getResourceAsStream("noTemplates.json"));
+
+        try (TemplatesIterator templatesIterator = new TemplatesIterator(niFiRestConnector, jsonFactory)) {
+            assertFalse(templatesIterator.hasNext());
+            templatesIterator.next();
+        } finally {
+            verify(httpURLConnection).disconnect();
+        }
+    }
+
+    @Test
+    public void testIteratorNoTemplates() throws ConfigurationProviderException, IOException {
+        when(httpURLConnection.getInputStream()).thenReturn(TemplatesIteratorTest.class.getClassLoader().getResourceAsStream("noTemplates.json"));
+        List<Pair<String, String>> idToNameList;
+        try (TemplatesIterator templatesIterator = new TemplatesIterator(niFiRestConnector, jsonFactory)) {
+            idToNameList = Lists.newArrayList(templatesIterator);
+        }
+        assertEquals(0, idToNameList.size());
+
+        verify(httpURLConnection).disconnect();
+    }
+
+    @Test
+    public void testIteratorSingleTemplate() throws ConfigurationProviderException, IOException {
+        when(httpURLConnection.getInputStream()).thenReturn(TemplatesIteratorTest.class.getClassLoader().getResourceAsStream("oneTemplate.json"));
+        List<Pair<String, String>> idToNameList;
+        try (TemplatesIterator templatesIterator = new TemplatesIterator(niFiRestConnector, jsonFactory)) {
+            idToNameList = Lists.newArrayList(templatesIterator);
+        }
+        assertEquals(1, idToNameList.size());
+        Pair<String, String> idNamePair = idToNameList.get(0);
+        assertEquals("d05845ae-ceda-4c50-b7c2-037e42ddf1d3", idNamePair.getFirst());
+        assertEquals("raspi3.v1", idNamePair.getSecond());
+
+        verify(httpURLConnection).disconnect();
+    }
+
+    @Test
+    public void testIteratorTwoTemplates() throws ConfigurationProviderException, IOException {
+        when(httpURLConnection.getInputStream()).thenReturn(TemplatesIteratorTest.class.getClassLoader().getResourceAsStream("twoTemplates.json"));
+        List<Pair<String, String>> idToNameList;
+        try (TemplatesIterator templatesIterator = new TemplatesIterator(niFiRestConnector, jsonFactory)) {
+            idToNameList = Lists.newArrayList(templatesIterator);
+        }
+        assertEquals(2, idToNameList.size());
+        Pair<String, String> idNamePair = idToNameList.get(0);
+        assertEquals("d05845ae-ceda-4c50-b7c2-037e42ddf1d3", idNamePair.getFirst());
+        assertEquals("raspi3.v1", idNamePair.getSecond());
+
+        idNamePair = idToNameList.get(1);
+        assertEquals("9384b48d-85b4-478a-bf3e-64d113f8fbc5", idNamePair.getFirst());
+        assertEquals("raspi3.v2", idNamePair.getSecond());
+
+        verify(httpURLConnection).disconnect();
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/resources/noTemplates.json
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/resources/noTemplates.json b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/resources/noTemplates.json
new file mode 100644
index 0000000..ff41507
--- /dev/null
+++ b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/resources/noTemplates.json
@@ -0,0 +1 @@
+{"templates":[],"generated":"14:55:13 EST"}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/resources/oneTemplate.json
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/resources/oneTemplate.json b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/resources/oneTemplate.json
new file mode 100644
index 0000000..0d981f1
--- /dev/null
+++ b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/resources/oneTemplate.json
@@ -0,0 +1,21 @@
+{
+    "generated": "10:26:04 EST",
+    "templates": [
+        {
+            "id": "d05845ae-ceda-4c50-b7c2-037e42ddf1d3",
+            "permissions": {
+                "canRead": true,
+                "canWrite": true
+            },
+            "template": {
+                "description": "",
+                "encoding-version": "1.0",
+                "groupId": "8f8eda5e-015a-1000-a9c1-b7e4fe10ae83",
+                "id": "d05845ae-ceda-4c50-b7c2-037e42ddf1d3",
+                "name": "raspi3.v1",
+                "timestamp": "03/02/2017 10:26:01 EST",
+                "uri": "http://localhost:8081/nifi-api/templates/d05845ae-ceda-4c50-b7c2-037e42ddf1d3"
+            }
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/resources/twoTemplates.json
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/resources/twoTemplates.json b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/resources/twoTemplates.json
new file mode 100644
index 0000000..9b4245a
--- /dev/null
+++ b/minifi-c2/minifi-c2-provider/minifi-c2-provider-nifi-rest/src/test/resources/twoTemplates.json
@@ -0,0 +1,37 @@
+{
+  "generated": "14:53:15 EST",
+  "templates": [
+    {
+      "id": "d05845ae-ceda-4c50-b7c2-037e42ddf1d3",
+      "permissions": {
+        "canRead": true,
+        "canWrite": true
+      },
+      "template": {
+        "description": "",
+        "encoding-version": "1.0",
+        "groupId": "8f8eda5e-015a-1000-a9c1-b7e4fe10ae83",
+        "id": "d05845ae-ceda-4c50-b7c2-037e42ddf1d3",
+        "name": "raspi3.v1",
+        "timestamp": "03/02/2017 10:26:01 EST",
+        "uri": "http://localhost:8081/nifi-api/templates/d05845ae-ceda-4c50-b7c2-037e42ddf1d3"
+      }
+    },
+    {
+      "id": "9384b48d-85b4-478a-bf3e-64d113f8fbc5",
+      "permissions": {
+        "canRead": true,
+        "canWrite": true
+      },
+      "template": {
+        "description": "",
+        "encoding-version": "1.0",
+        "groupId": "8f8eda5e-015a-1000-a9c1-b7e4fe10ae83",
+        "id": "9384b48d-85b4-478a-bf3e-64d113f8fbc5",
+        "name": "raspi3.v2",
+        "timestamp": "03/02/2017 13:08:14 EST",
+        "uri": "http://localhost:8081/nifi-api/templates/9384b48d-85b4-478a-bf3e-64d113f8fbc5"
+      }
+    }
+  ]
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-provider/pom.xml
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-provider/pom.xml b/minifi-c2/minifi-c2-provider/pom.xml
new file mode 100644
index 0000000..fc0fbae
--- /dev/null
+++ b/minifi-c2/minifi-c2-provider/pom.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>minifi-c2</artifactId>
+        <groupId>org.apache.nifi.minifi</groupId>
+        <version>0.2.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>minifi-c2-provider</artifactId>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>minifi-c2-provider-cache</module>
+        <module>minifi-c2-provider-nifi-rest</module>
+    </modules>
+</project>

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-service/pom.xml
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-service/pom.xml b/minifi-c2/minifi-c2-service/pom.xml
new file mode 100644
index 0000000..eb52d7d
--- /dev/null
+++ b/minifi-c2/minifi-c2-service/pom.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>minifi-c2</artifactId>
+        <groupId>org.apache.nifi.minifi</groupId>
+        <version>0.2.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>minifi-c2-service</artifactId>
+    <packaging>war</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.nifi.minifi</groupId>
+            <artifactId>minifi-c2-api</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-beans</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-web</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-config</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.yaml</groupId>
+            <artifactId>snakeyaml</artifactId>
+            <version>1.17</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.ws.rs</groupId>
+            <artifactId>jsr311-api</artifactId>
+            <version>1.1.1</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.wordnik</groupId>
+            <artifactId>swagger-annotations</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-service/src/main/java/org/apache/nifi/minifi/c2/configuration/Configuration.java
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-service/src/main/java/org/apache/nifi/minifi/c2/configuration/Configuration.java b/minifi-c2/minifi-c2-service/src/main/java/org/apache/nifi/minifi/c2/configuration/Configuration.java
new file mode 100644
index 0000000..19b647f
--- /dev/null
+++ b/minifi-c2/minifi-c2-service/src/main/java/org/apache/nifi/minifi/c2/configuration/Configuration.java
@@ -0,0 +1,28 @@
+/*
+ * 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.minifi.c2.configuration;
+
+import org.apache.nifi.minifi.c2.security.SecurityConfiguration;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.ImportResource;
+
+@org.springframework.context.annotation.Configuration
+@Import({SecurityConfiguration.class})
+@ImportResource({"classpath:minifi-c2-context.xml"})
+public class Configuration {
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-service/src/main/java/org/apache/nifi/minifi/c2/security/SecurityConfiguration.java
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-service/src/main/java/org/apache/nifi/minifi/c2/security/SecurityConfiguration.java b/minifi-c2/minifi-c2-service/src/main/java/org/apache/nifi/minifi/c2/security/SecurityConfiguration.java
new file mode 100644
index 0000000..2c4630c
--- /dev/null
+++ b/minifi-c2/minifi-c2-service/src/main/java/org/apache/nifi/minifi/c2/security/SecurityConfiguration.java
@@ -0,0 +1,91 @@
+/*
+ * 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.minifi.c2.security;
+
+import org.apache.nifi.minifi.c2.security.authentication.C2AnonymousAuthenticationFilter;
+import org.apache.nifi.minifi.c2.security.authentication.X509AuthenticationFilter;
+import org.apache.nifi.minifi.c2.security.authentication.X509AuthenticationProvider;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.ImportResource;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.AuthenticationProvider;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+@ImportResource({"classpath:minifi-c2-web-security-context.xml"})
+public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
+    private AuthenticationProvider authenticationProvider;
+    private X509AuthenticationFilter x509AuthenticationFilter;
+    private C2AnonymousAuthenticationFilter c2AnonymousAuthenticationFilter;
+
+    public SecurityConfiguration() {
+        super(true);
+    }
+
+    @Bean
+    @Override
+    public AuthenticationManager authenticationManagerBean() throws Exception {
+        // override xxxBean method so the authentication manager is available in app context (necessary for the method level security)
+        return super.authenticationManagerBean();
+    }
+
+    @Override
+    public void configure(WebSecurity web) throws Exception {
+        web.ignoring().antMatchers("/access", "/access/config", "/access/token", "/access/kerberos");
+    }
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        http
+                .rememberMe().disable().authorizeRequests().anyRequest().fullyAuthenticated().and()
+                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
+        http.addFilterBefore(x509AuthenticationFilter, AnonymousAuthenticationFilter.class);
+        http.anonymous().authenticationFilter(c2AnonymousAuthenticationFilter);
+    }
+
+    @Override
+    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+        auth.authenticationProvider(authenticationProvider);
+    }
+
+    @Autowired
+    public void setX509AuthenticationProvider(X509AuthenticationProvider x509AuthenticationProvider) {
+        this.authenticationProvider = x509AuthenticationProvider;
+    }
+
+    @Autowired
+    public void setX509AuthenticationFilter(X509AuthenticationFilter x509AuthenticationFilter) {
+        this.x509AuthenticationFilter = x509AuthenticationFilter;
+    }
+
+    @Autowired
+    public void setC2AnonymousAuthenticationFilter(C2AnonymousAuthenticationFilter c2AnonymousAuthenticationFilter) {
+        this.c2AnonymousAuthenticationFilter = c2AnonymousAuthenticationFilter;
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/f89f4150/minifi-c2/minifi-c2-service/src/main/java/org/apache/nifi/minifi/c2/security/authentication/C2AnonymousAuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-service/src/main/java/org/apache/nifi/minifi/c2/security/authentication/C2AnonymousAuthenticationFilter.java b/minifi-c2/minifi-c2-service/src/main/java/org/apache/nifi/minifi/c2/security/authentication/C2AnonymousAuthenticationFilter.java
new file mode 100644
index 0000000..e73d2ee
--- /dev/null
+++ b/minifi-c2/minifi-c2-service/src/main/java/org/apache/nifi/minifi/c2/security/authentication/C2AnonymousAuthenticationFilter.java
@@ -0,0 +1,38 @@
+/*
+ * 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.minifi.c2.security.authentication;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Arrays;
+
+public class C2AnonymousAuthenticationFilter extends AnonymousAuthenticationFilter {
+    public static final String ANONYMOUS = "anonymous";
+
+    public C2AnonymousAuthenticationFilter() {
+        super(ANONYMOUS);
+    }
+
+    @Override
+    protected Authentication createAuthentication(HttpServletRequest request) {
+        return new C2AuthenticationToken(ANONYMOUS, null, Arrays.asList(new SimpleGrantedAuthority("ROLE_ANONYMOUS")));
+    }
+}