You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by kd...@apache.org on 2018/09/22 02:11:21 UTC
[22/51] [partial] nifi-registry git commit: NIFIREG-201 Refactoring
project structure to better isolate extensions
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-resources/src/main/resources/bin/run-nifi-registry.bat
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-resources/src/main/resources/bin/run-nifi-registry.bat b/nifi-registry-core/nifi-registry-resources/src/main/resources/bin/run-nifi-registry.bat
new file mode 100644
index 0000000..c8d6541
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-resources/src/main/resources/bin/run-nifi-registry.bat
@@ -0,0 +1,50 @@
+@echo off
+rem
+rem Licensed to the Apache Software Foundation (ASF) under one or more
+rem contributor license agreements. See the NOTICE file distributed with
+rem this work for additional information regarding copyright ownership.
+rem The ASF licenses this file to You under the Apache License, Version 2.0
+rem (the "License"); you may not use this file except in compliance with
+rem the License. You may obtain a copy of the License at
+rem
+rem http://www.apache.org/licenses/LICENSE-2.0
+rem
+rem Unless required by applicable law or agreed to in writing, software
+rem distributed under the License is distributed on an "AS IS" BASIS,
+rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+rem See the License for the specific language governing permissions and
+rem limitations under the License.
+rem
+
+rem Use JAVA_HOME if it's set; otherwise, just use java
+
+if "%JAVA_HOME%" == "" goto noJavaHome
+if not exist "%JAVA_HOME%\bin\java.exe" goto noJavaHome
+set JAVA_EXE=%JAVA_HOME%\bin\java.exe
+goto startNiFiRegistry
+
+:noJavaHome
+echo The JAVA_HOME environment variable is not defined correctly.
+echo Instead the PATH will be used to find the java executable.
+echo.
+set JAVA_EXE=java
+goto startNiFiRegistry
+
+:startNiFiRegistry
+set NIFI_REGISTRY_ROOT=%~dp0..
+pushd "%NIFI_REGISTRY_ROOT%\"
+set LIB_DIR=%NIFI_REGISTRY_ROOT%\lib
+set SHARED_DIR=%NIFI_REGISTRY_ROOT%\lib\shared
+set BOOTSTRAP_DIR=%NIFI_REGISTRY_ROOT%\lib\bootstrap
+set CONF_DIR=%NIFI_REGISTRY_ROOT%\conf
+
+set BOOTSTRAP_CONF_FILE=%CONF_DIR%\bootstrap.conf
+set JAVA_ARGS=-Dorg.apache.nifi.registry.bootstrap.config.file=%BOOTSTRAP_CONF_FILE%
+
+SET JAVA_PARAMS=-cp %CONF_DIR%;%LIB_DIR%\*;%SHARED_DIR%\*;%BOOTSTRAP_DIR%\* -Xms512m -Xmx1024m %JAVA_ARGS% org.apache.nifi.registry.NiFiRegistry
+set BOOTSTRAP_ACTION=run
+
+echo cmd.exe /C "%JAVA_EXE%" %JAVA_PARAMS% %BOOTSTRAP_ACTION%
+cmd.exe /C "%JAVA_EXE%" %JAVA_PARAMS% %BOOTSTRAP_ACTION%
+
+popd
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-resources/src/main/resources/bin/status-nifi-registry.bat
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-resources/src/main/resources/bin/status-nifi-registry.bat b/nifi-registry-core/nifi-registry-resources/src/main/resources/bin/status-nifi-registry.bat
new file mode 100644
index 0000000..30a29a0
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-resources/src/main/resources/bin/status-nifi-registry.bat
@@ -0,0 +1,49 @@
+@echo off
+rem
+rem Licensed to the Apache Software Foundation (ASF) under one or more
+rem contributor license agreements. See the NOTICE file distributed with
+rem this work for additional information regarding copyright ownership.
+rem The ASF licenses this file to You under the Apache License, Version 2.0
+rem (the "License"); you may not use this file except in compliance with
+rem the License. You may obtain a copy of the License at
+rem
+rem http://www.apache.org/licenses/LICENSE-2.0
+rem
+rem Unless required by applicable law or agreed to in writing, software
+rem distributed under the License is distributed on an "AS IS" BASIS,
+rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+rem See the License for the specific language governing permissions and
+rem limitations under the License.
+rem
+
+rem Use JAVA_HOME if it's set; otherwise, just use java
+
+if "%JAVA_HOME%" == "" goto noJavaHome
+if not exist "%JAVA_HOME%\bin\java.exe" goto noJavaHome
+set JAVA_EXE=%JAVA_HOME%\bin\java.exe
+goto startNiFiRegistry
+
+:noJavaHome
+echo The JAVA_HOME environment variable is not defined correctly.
+echo Instead the PATH will be used to find the java executable.
+echo.
+set JAVA_EXE=java
+goto startNiFiRegistry
+
+:startNiFiRegistry
+set NIFI_REGISTRY_ROOT=%~dp0..\
+pushd "%NIFI_REGISTRY_ROOT%"
+set LIB_DIR=%NIFI_REGISTRY_ROOT%\lib
+set SHARED_DIR=%NIFI_REGISTRY_ROOT%\lib\shared
+set BOOTSTRAP_DIR=%NIFI_REGISTRY_ROOT%\lib\bootstrap
+set CONF_DIR=conf
+
+set BOOTSTRAP_CONF_FILE=%CONF_DIR%\bootstrap.conf
+set JAVA_ARGS=-Dorg.apache.nifi.registry.bootstrap.config.file=%BOOTSTRAP_CONF_FILE%
+
+set JAVA_PARAMS=-cp %LIB_DIR%\*;%SHARED_DIR%\*;%BOOTSTRAP_DIR%\* -Xms12m -Xmx24m %JAVA_ARGS% org.apache.nifi.registry.NiFiRegistry
+set BOOTSTRAP_ACTION=status
+
+cmd.exe /C "%JAVA_EXE%" %JAVA_PARAMS% %BOOTSTRAP_ACTION%
+
+popd
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/authorizers.xml
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/authorizers.xml b/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/authorizers.xml
new file mode 100644
index 0000000..772db61
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/authorizers.xml
@@ -0,0 +1,256 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ 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.
+-->
+<!--
+ This file lists the userGroupProviders, accessPolicyProviders, and authorizers to use when running securely. In order
+ to use a specific authorizer it must be configured here and its identifier must be specified in the nifi-registry.properties file.
+ If the authorizer is a managedAuthorizer, it may need to be configured with an accessPolicyProvider and an userGroupProvider.
+ This file allows for configuration of them, but they must be configured in order:
+
+ ...
+ all userGroupProviders
+ all accessPolicyProviders
+ all Authorizers
+ ...
+-->
+<authorizers>
+
+ <!--
+ The FileUserGroupProvider will provide support for managing users and groups which is backed by a file
+ on the local file system.
+
+ - Users File - The file where the FileUserGroupProvider will store users and groups.
+
+ - Initial User Identity [unique key] - The identity of a users and systems to seed the Users File. The name of
+ each property must be unique, for example: "Initial User Identity A", "Initial User Identity B",
+ "Initial User Identity C" or "Initial User Identity 1", "Initial User Identity 2", "Initial User Identity 3"
+
+ NOTE: Any identity mapping rules specified in nifi-registry.properties will also be applied to the user identities,
+ so the values should be the unmapped identities (i.e. full DN from a certificate).
+ -->
+ <userGroupProvider>
+ <identifier>file-user-group-provider</identifier>
+ <class>org.apache.nifi.registry.security.authorization.file.FileUserGroupProvider</class>
+ <property name="Users File">./conf/users.xml</property>
+ <property name="Initial User Identity 1"><!--CN=abc, OU=xyz--></property>
+ </userGroupProvider>
+
+ <!--
+ The LdapUserGroupProvider will retrieve users and groups from an LDAP server. The users and groups
+ are not configurable.
+
+ 'Authentication Strategy' - How the connection to the LDAP server is authenticated. Possible
+ values are ANONYMOUS, SIMPLE, LDAPS, or START_TLS.
+
+ 'Manager DN' - The DN of the manager that is used to bind to the LDAP server to search for users.
+ 'Manager Password' - The password of the manager that is used to bind to the LDAP server to
+ search for users.
+
+ 'TLS - Keystore' - Path to the Keystore that is used when connecting to LDAP using LDAPS or START_TLS.
+ 'TLS - Keystore Password' - Password for the Keystore that is used when connecting to LDAP
+ using LDAPS or START_TLS.
+ 'TLS - Keystore Type' - Type of the Keystore that is used when connecting to LDAP using
+ LDAPS or START_TLS (i.e. JKS or PKCS12).
+ 'TLS - Truststore' - Path to the Truststore that is used when connecting to LDAP using LDAPS or START_TLS.
+ 'TLS - Truststore Password' - Password for the Truststore that is used when connecting to
+ LDAP using LDAPS or START_TLS.
+ 'TLS - Truststore Type' - Type of the Truststore that is used when connecting to LDAP using
+ LDAPS or START_TLS (i.e. JKS or PKCS12).
+ 'TLS - Client Auth' - Client authentication policy when connecting to LDAP using LDAPS or START_TLS.
+ Possible values are REQUIRED, WANT, NONE.
+ 'TLS - Protocol' - Protocol to use when connecting to LDAP using LDAPS or START_TLS. (i.e. TLS,
+ TLSv1.1, TLSv1.2, etc).
+ 'TLS - Shutdown Gracefully' - Specifies whether the TLS should be shut down gracefully
+ before the target context is closed. Defaults to false.
+
+ 'Referral Strategy' - Strategy for handling referrals. Possible values are FOLLOW, IGNORE, THROW.
+ 'Connect Timeout' - Duration of connect timeout. (i.e. 10 secs).
+ 'Read Timeout' - Duration of read timeout. (i.e. 10 secs).
+
+ 'Url' - Space-separated list of URLs of the LDAP servers (i.e. ldap://<hostname>:<port>).
+ 'Page Size' - Sets the page size when retrieving users and groups. If not specified, no paging is performed.
+ 'Sync Interval' - Duration of time between syncing users and groups. (i.e. 30 mins).
+
+ 'User Search Base' - Base DN for searching for users (i.e. ou=users,o=nifi). Required to search users.
+ 'User Object Class' - Object class for identifying users (i.e. person). Required if searching users.
+ 'User Search Scope' - Search scope for searching users (ONE_LEVEL, OBJECT, or SUBTREE). Required if searching users.
+ 'User Search Filter' - Filter for searching for users against the 'User Search Base' (i.e. (memberof=cn=team1,ou=groups,o=nifi) ). Optional.
+ 'User Identity Attribute' - Attribute to use to extract user identity (i.e. cn). Optional. If not set, the entire DN is used.
+ 'User Group Name Attribute' - Attribute to use to define group membership (i.e. memberof). Optional. If not set
+ group membership will not be calculated through the users. Will rely on group membership being defined
+ through 'Group Member Attribute' if set. The value of this property is the name of the attribute in the user ldap entry that
+ associates them with a group. The value of that user attribute could be a dn or group name for instance. What value is expected
+ is configured in the 'User Group Name Attribute - Referenced Group Attribute'.
+ 'User Group Name Attribute - Referenced Group Attribute' - If blank, the value of the attribute defined in 'User Group Name Attribute'
+ is expected to be the full dn of the group. If not blank, this property will define the attribute of the group ldap entry that
+ the value of the attribute defined in 'User Group Name Attribute' is referencing (i.e. name). Use of this property requires that
+ 'Group Search Base' is also configured.
+
+ 'Group Search Base' - Base DN for searching for groups (i.e. ou=groups,o=nifi). Required to search groups.
+ 'Group Object Class' - Object class for identifying groups (i.e. groupOfNames). Required if searching groups.
+ 'Group Search Scope' - Search scope for searching groups (ONE_LEVEL, OBJECT, or SUBTREE). Required if searching groups.
+ 'Group Search Filter' - Filter for searching for groups against the 'Group Search Base'. Optional.
+ 'Group Name Attribute' - Attribute to use to extract group name (i.e. cn). Optional. If not set, the entire DN is used.
+ 'Group Member Attribute' - Attribute to use to define group membership (i.e. member). Optional. If not set
+ group membership will not be calculated through the groups. Will rely on group membership being defined
+ through 'User Group Name Attribute' if set. The value of this property is the name of the attribute in the group ldap entry that
+ associates them with a user. The value of that group attribute could be a dn or memberUid for instance. What value is expected
+ is configured in the 'Group Member Attribute - Referenced User Attribute'. (i.e. member: cn=User 1,ou=users,o=nifi-registry vs. memberUid: user1)
+ 'Group Member Attribute - Referenced User Attribute' - If blank, the value of the attribute defined in 'Group Member Attribute'
+ is expected to be the full dn of the user. If not blank, this property will define the attribute of the user ldap entry that
+ the value of the attribute defined in 'Group Member Attribute' is referencing (i.e. uid). Use of this property requires that
+ 'User Search Base' is also configured. (i.e. member: cn=User 1,ou=users,o=nifi-registry vs. memberUid: user1)
+
+ NOTE: Any identity mapping rules specified in nifi-registry.properties will also be applied to the user identities.
+ Group names are not mapped.
+ -->
+ <!-- To enable the ldap-user-group-provider remove 2 lines. This is 1 of 2.
+ <userGroupProvider>
+ <identifier>ldap-user-group-provider</identifier>
+ <class>org.apache.nifi.registry.security.ldap.tenants.LdapUserGroupProvider</class>
+ <property name="Authentication Strategy">START_TLS</property>
+
+ <property name="Manager DN"></property>
+ <property name="Manager Password"></property>
+
+ <property name="TLS - Keystore"></property>
+ <property name="TLS - Keystore Password"></property>
+ <property name="TLS - Keystore Type"></property>
+ <property name="TLS - Truststore"></property>
+ <property name="TLS - Truststore Password"></property>
+ <property name="TLS - Truststore Type"></property>
+ <property name="TLS - Client Auth"></property>
+ <property name="TLS - Protocol"></property>
+ <property name="TLS - Shutdown Gracefully"></property>
+
+ <property name="Referral Strategy">FOLLOW</property>
+ <property name="Connect Timeout">10 secs</property>
+ <property name="Read Timeout">10 secs</property>
+
+ <property name="Url"></property>
+ <property name="Page Size"></property>
+ <property name="Sync Interval">30 mins</property>
+
+ <property name="User Search Base"></property>
+ <property name="User Object Class">person</property>
+ <property name="User Search Scope">ONE_LEVEL</property>
+ <property name="User Search Filter"></property>
+ <property name="User Identity Attribute"></property>
+ <property name="User Group Name Attribute"></property>
+ <property name="User Group Name Attribute - Referenced Group Attribute"></property>
+
+ <property name="Group Search Base"></property>
+ <property name="Group Object Class">group</property>
+ <property name="Group Search Scope">ONE_LEVEL</property>
+ <property name="Group Search Filter"></property>
+ <property name="Group Name Attribute"></property>
+ <property name="Group Member Attribute"></property>
+ <property name="Group Member Attribute - Referenced User Attribute"></property>
+ </userGroupProvider>
+ To enable the ldap-user-group-provider remove 2 lines. This is 2 of 2. -->
+
+ <!--
+ The CompositeUserGroupProvider will provide support for retrieving users and groups from multiple sources.
+
+ - User Group Provider [unique key] - The identifier of user group providers to load from. The name of
+ each property must be unique, for example: "User Group Provider A", "User Group Provider B",
+ "User Group Provider C" or "User Group Provider 1", "User Group Provider 2", "User Group Provider 3"
+
+ NOTE: Any identity mapping rules specified in nifi-registry.properties are not applied in this implementation. This
+ behavior would need to be applied by the base implementation.
+ -->
+ <!-- To enable the composite-user-group-provider remove 2 lines. This is 1 of 2.
+ <userGroupProvider>
+ <identifier>composite-user-group-provider</identifier>
+ <class>org.apache.nifi.registry.security.authorization.CompositeUserGroupProvider</class>
+ <property name="User Group Provider 1"></property>
+ </userGroupProvider>
+ To enable the composite-user-group-provider remove 2 lines. This is 2 of 2. -->
+
+ <!--
+ The CompositeConfigurableUserGroupProvider will provide support for retrieving users and groups from multiple sources.
+ Additionally, a single configurable user group provider is required. Users from the configurable user group provider
+ are configurable, however users loaded from one of the User Group Provider [unique key] will not be.
+
+ - Configurable User Group Provider - A configurable user group provider.
+
+ - User Group Provider [unique key] - The identifier of user group providers to load from. The name of
+ each property must be unique, for example: "User Group Provider A", "User Group Provider B",
+ "User Group Provider C" or "User Group Provider 1", "User Group Provider 2", "User Group Provider 3"
+
+ NOTE: Any identity mapping rules specified in nifi-registry.properties are not applied in this implementation. This
+ behavior would need to be applied by the base implementation.
+ -->
+ <!-- To enable the composite-configurable-user-group-provider remove 2 lines. This is 1 of 2.
+ <userGroupProvider>
+ <identifier>composite-configurable-user-group-provider</identifier>
+ <class>org.apache.nifi.registry.security.authorization.CompositeConfigurableUserGroupProvider</class>
+ <property name="Configurable User Group Provider">file-user-group-provider</property>
+ <property name="User Group Provider 1"></property>
+ </userGroupProvider>
+ To enable the composite-configurable-user-group-provider remove 2 lines. This is 2 of 2. -->
+
+ <!--
+ The FileAccessPolicyProvider will provide support for managing access policies which is backed by a file
+ on the local file system.
+
+ - User Group Provider - The identifier for an User Group Provider defined above that will be used to access
+ users and groups for use in the managed access policies.
+
+ - Authorizations File - The file where the FileAccessPolicyProvider will store policies.
+
+ - Initial Admin Identity - The identity of an initial admin user that will be granted access to the UI and
+ given the ability to create additional users, groups, and policies. The value of this property could be
+ a DN when using certificates or LDAP. This property will only be used when there
+ are no other policies defined.
+
+ NOTE: Any identity mapping rules specified in nifi-registry.properties will also be applied to the initial admin identity,
+ so the value should be the unmapped identity. This identity must be found in the configured User Group Provider.
+
+ - NiFi Identity [unique key] - The identity of a NiFi node that will have access to this NiFi Registry and will be able
+ to act as a proxy on behalf of a NiFi Registry end user. A property should be created for the identity of every NiFi
+ node that needs to access this NiFi Registry. The name of each property must be unique, for example for three
+ NiFi clients:
+ "NiFi Identity A", "NiFi Identity B", "NiFi Identity C" or "NiFi Identity 1", "NiFi Identity 2", "NiFi Identity 3"
+
+ NOTE: Any identity mapping rules specified in nifi-registry.properties will also be applied to the nifi identities,
+ so the values should be the unmapped identities (i.e. full DN from a certificate). This identity must be found
+ in the configured User Group Provider.
+ -->
+ <accessPolicyProvider>
+ <identifier>file-access-policy-provider</identifier>
+ <class>org.apache.nifi.registry.security.authorization.file.FileAccessPolicyProvider</class>
+ <property name="User Group Provider">file-user-group-provider</property>
+ <property name="Authorizations File">./conf/authorizations.xml</property>
+ <property name="Initial Admin Identity"><!-- CN=abc, OU=xyz --></property>
+
+ <!--<property name="NiFi Identity 1"></property>-->
+ </accessPolicyProvider>
+
+ <!--
+ The StandardManagedAuthorizer. This authorizer implementation must be configured with the
+ Access Policy Provider which it will use to access and manage users, groups, and policies.
+ These users, groups, and policies will be used to make all access decisions during authorization
+ requests.
+
+ - Access Policy Provider - The identifier for an Access Policy Provider defined above.
+ -->
+ <authorizer>
+ <identifier>managed-authorizer</identifier>
+ <class>org.apache.nifi.registry.security.authorization.StandardManagedAuthorizer</class>
+ <property name="Access Policy Provider">file-access-policy-provider</property>
+ </authorizer>
+
+</authorizers>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/bootstrap.conf
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/bootstrap.conf b/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/bootstrap.conf
new file mode 100644
index 0000000..637eb64
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/bootstrap.conf
@@ -0,0 +1,48 @@
+#
+# 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.
+#
+
+# Java command to use when running nifi-registry
+java=java
+
+# Username to use when running nifi-registry. This value will be ignored on Windows.
+run.as=
+
+# Configure where nifi-registry's lib and conf directories live
+lib.dir=./lib
+conf.dir=./conf
+
+# How long to wait after telling nifi-registry to shutdown before explicitly killing the Process
+graceful.shutdown.seconds=20
+
+# Disable JSR 199 so that we can use JSP's without running a JDK
+java.arg.1=-Dorg.apache.jasper.compiler.disablejsr199=true
+
+# JVM memory settings
+java.arg.2=-Xms512m
+java.arg.3=-Xmx512m
+
+# Enable Remote Debugging
+#java.arg.debug=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000
+
+java.arg.4=-Djava.net.preferIPv4Stack=true
+
+# allowRestrictedHeaders is required for Cluster/Node communications to work properly
+java.arg.5=-Dsun.net.http.allowRestrictedHeaders=true
+java.arg.6=-Djava.protocol.handler.pkgs=sun.net.www.protocol
+
+# Master key in hexadecimal format for encrypted sensitive configuration values
+nifi.registry.bootstrap.sensitive.key=
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/identity-providers.xml
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/identity-providers.xml b/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/identity-providers.xml
new file mode 100644
index 0000000..1e8cf64
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/identity-providers.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ~ 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.
+ -->
+<!--
+ This file lists the identity providers to use when running securely. In order
+ to use a specific provider it must be configured here and its identifier
+ must be specified in the nifi-registry.properties file.
+-->
+<identityProviders>
+ <!--
+ Identity Provider for users logging in with username/password against an LDAP server.
+
+ 'Authentication Strategy' - How the connection to the LDAP server is authenticated. Possible
+ values are ANONYMOUS, SIMPLE, LDAPS, or START_TLS.
+
+ 'Manager DN' - The DN of the manager that is used to bind to the LDAP server to search for users.
+ 'Manager Password' - The password of the manager that is used to bind to the LDAP server to
+ search for users.
+
+ 'TLS - Keystore' - Path to the Keystore that is used when connecting to LDAP using LDAPS or START_TLS.
+ 'TLS - Keystore Password' - Password for the Keystore that is used when connecting to LDAP
+ using LDAPS or START_TLS.
+ 'TLS - Keystore Type' - Type of the Keystore that is used when connecting to LDAP using
+ LDAPS or START_TLS (i.e. JKS or PKCS12).
+ 'TLS - Truststore' - Path to the Truststore that is used when connecting to LDAP using LDAPS or START_TLS.
+ 'TLS - Truststore Password' - Password for the Truststore that is used when connecting to
+ LDAP using LDAPS or START_TLS.
+ 'TLS - Truststore Type' - Type of the Truststore that is used when connecting to LDAP using
+ LDAPS or START_TLS (i.e. JKS or PKCS12).
+ 'TLS - Client Auth' - Client authentication policy when connecting to LDAP using LDAPS or START_TLS.
+ Possible values are REQUIRED, WANT, NONE.
+ 'TLS - Protocol' - Protocol to use when connecting to LDAP using LDAPS or START_TLS. (i.e. TLS,
+ TLSv1.1, TLSv1.2, etc).
+ 'TLS - Shutdown Gracefully' - Specifies whether the TLS should be shut down gracefully
+ before the target context is closed. Defaults to false.
+
+ 'Referral Strategy' - Strategy for handling referrals. Possible values are FOLLOW, IGNORE, THROW.
+ 'Connect Timeout' - Duration of connect timeout. (i.e. 10 secs).
+ 'Read Timeout' - Duration of read timeout. (i.e. 10 secs).
+
+ 'Url' - Space-separated list of URLs of the LDAP servers (i.e. ldap://<hostname>:<port>).
+ 'User Search Base' - Base DN for searching for users (i.e. CN=Users,DC=example,DC=com).
+ 'User Search Filter' - Filter for searching for users against the 'User Search Base'.
+ (i.e. sAMAccountName={0}). The user specified name is inserted into '{0}'.
+
+ 'Identity Strategy' - Strategy to identify users. Possible values are USE_DN and USE_USERNAME.
+ The default functionality if this property is missing is USE_DN in order to retain
+ backward compatibility. USE_DN will use the full DN of the user entry if possible.
+ USE_USERNAME will use the username the user logged in with.
+ 'Authentication Expiration' - The duration of how long the user authentication is valid
+ for. If the user never logs out, they will be required to log back in following
+ this duration.
+ -->
+ <!-- To enable the ldap-identity-provider remove 2 lines. This is 1 of 2.
+ <provider>
+ <identifier>ldap-identity-provider</identifier>
+ <class>org.apache.nifi.registry.security.ldap.LdapIdentityProvider</class>
+ <property name="Authentication Strategy">SIMPLE</property>
+
+ <property name="Manager DN"></property>
+ <property name="Manager Password"></property>
+
+ <property name="Referral Strategy">FOLLOW</property>
+ <property name="Connect Timeout">10 secs</property>
+ <property name="Read Timeout">10 secs</property>
+
+ <property name="Url"></property>
+ <property name="User Search Base"></property>
+ <property name="User Search Filter"></property>
+
+ <property name="Identity Strategy">USE_USERNAME</property>
+ <property name="Authentication Expiration">12 hours</property>
+ </provider>
+ To enable the ldap-identity-provider remove 2 lines. This is 2 of 2. -->
+
+ <!--
+ Identity Provider for users logging in with username/password against a Kerberos KDC server.
+
+ 'Default Realm' - Default realm to provide when user enters incomplete user principal (i.e. NIFI.APACHE.ORG).
+ 'Authentication Expiration' - The duration of how long the user authentication is valid for. If the user never logs out, they will be required to log back in following this duration.
+ -->
+ <!-- To enable the kerberos-identity-provider remove 2 lines. This is 1 of 2.
+ <provider>
+ <identifier>kerberos-identity-provider</identifier>
+ <class>org.apache.nifi.registry.web.security.authentication.kerberos.KerberosIdentityProvider</class>
+ <property name="Default Realm">NIFI.APACHE.ORG</property>
+ <property name="Authentication Expiration">12 hours</property>
+ <property name="Enable Debug">false</property>
+ </provider>
+ To enable the kerberos-provider remove 2 lines. This is 2 of 2. -->
+
+</identityProviders>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/logback.xml
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/logback.xml b/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/logback.xml
new file mode 100644
index 0000000..7d65bda
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/logback.xml
@@ -0,0 +1,124 @@
+<?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.
+-->
+<configuration scan="true" scanPeriod="30 seconds">
+ <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
+ <resetJUL>true</resetJUL>
+ </contextListener>
+
+ <appender name="APP_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>logs/nifi-registry-app.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <!--
+ For daily rollover, use 'app_%d.log'.
+ For hourly rollover, use 'app_%d{yyyy-MM-dd_HH}.log'.
+ To GZIP rolled files, replace '.log' with '.log.gz'.
+ To ZIP rolled files, replace '.log' with '.log.zip'.
+ -->
+ <fileNamePattern>./logs/nifi-registry-app_%d{yyyy-MM-dd_HH}.%i.log</fileNamePattern>
+ <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+ <maxFileSize>100MB</maxFileSize>
+ </timeBasedFileNamingAndTriggeringPolicy>
+ <!-- keep 30 log files worth of history -->
+ <maxHistory>30</maxHistory>
+ </rollingPolicy>
+ <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+ <pattern>%date %level [%thread] %logger{40} %msg%n</pattern>
+ <immediateFlush>true</immediateFlush>
+ </encoder>
+ </appender>
+
+ <appender name="BOOTSTRAP_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${org.apache.nifi.registry.bootstrap.config.log.dir}/nifi-registry-bootstrap.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <!--
+ For daily rollover, use 'user_%d.log'.
+ For hourly rollover, use 'user_%d{yyyy-MM-dd_HH}.log'.
+ To GZIP rolled files, replace '.log' with '.log.gz'.
+ To ZIP rolled files, replace '.log' with '.log.zip'.
+ -->
+ <fileNamePattern>${org.apache.nifi.registry.bootstrap.config.log.dir}/nifi-registry-bootstrap_%d.log</fileNamePattern>
+ <!-- keep 5 log files worth of history -->
+ <maxHistory>5</maxHistory>
+ </rollingPolicy>
+ <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+ <pattern>%date %level [%thread] %logger{40} %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="EVENTS_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${org.apache.nifi.registry.bootstrap.config.log.dir}/nifi-registry-event.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <!--
+ For daily rollover, use 'user_%d.log'.
+ For hourly rollover, use 'user_%d{yyyy-MM-dd_HH}.log'.
+ To GZIP rolled files, replace '.log' with '.log.gz'.
+ To ZIP rolled files, replace '.log' with '.log.zip'.
+ -->
+ <fileNamePattern>${org.apache.nifi.registry.bootstrap.config.log.dir}/nifi-registry-event_%d.log</fileNamePattern>
+ <!-- keep 5 log files worth of history -->
+ <maxHistory>5</maxHistory>
+ </rollingPolicy>
+ <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+ <pattern>%date ## %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+ <pattern>%date %level [%thread] %logger{40} %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <!-- valid logging levels: TRACE, DEBUG, INFO, WARN, ERROR -->
+
+ <logger name="org.apache.nifi.registry" level="INFO"/>
+
+ <!-- To see SQL statements set this to DEBUG -->
+ <logger name="org.hibernate.SQL" level="INFO" />
+ <!-- To see the values in SQL statements set this to TRACE -->
+ <logger name="org.hibernate.type" level="INFO" />
+
+ <!--
+ Logger for capturing Bootstrap logs and NiFi Registry's standard error and standard out.
+ -->
+ <logger name="org.apache.nifi.registry.bootstrap" level="INFO" additivity="false">
+ <appender-ref ref="BOOTSTRAP_FILE" />
+ </logger>
+ <logger name="org.apache.nifi.registry.bootstrap.Command" level="INFO" additivity="false">
+ <appender-ref ref="CONSOLE" />
+ <appender-ref ref="BOOTSTRAP_FILE" />
+ </logger>
+
+ <!-- Everything written to NiFi Registry's Standard Out will be logged with the logger org.apache.nifi.StdOut at INFO level -->
+ <logger name="org.apache.nifi.registry.StdOut" level="INFO" additivity="false">
+ <appender-ref ref="BOOTSTRAP_FILE" />
+ </logger>
+
+ <!-- Everything written to NiFi Registry's Standard Error will be logged with the logger org.apache.nifi.StdErr at ERROR level -->
+ <logger name="org.apache.nifi.registry.StdErr" level="ERROR" additivity="false">
+ <appender-ref ref="BOOTSTRAP_FILE" />
+ </logger>
+
+ <!-- This will log all events to a separate file when the LoggingEventHookProvider is enabled in providers.xml -->
+ <logger name="org.apache.nifi.registry.provider.hook.LoggingEventHookProvider" level="INFO" additivity="false">
+ <appender-ref ref="EVENTS_FILE" />
+ </logger>
+
+ <root level="INFO">
+ <appender-ref ref="APP_FILE"/>
+ </root>
+
+</configuration>
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/nifi-registry.properties
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/nifi-registry.properties b/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/nifi-registry.properties
new file mode 100644
index 0000000..fb77a07
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/nifi-registry.properties
@@ -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.
+
+# web properties #
+nifi.registry.web.war.directory=${nifi.registry.web.war.directory}
+nifi.registry.web.http.host=${nifi.registry.web.http.host}
+nifi.registry.web.http.port=${nifi.registry.web.http.port}
+nifi.registry.web.https.host=${nifi.registry.web.https.host}
+nifi.registry.web.https.port=${nifi.registry.web.https.port}
+nifi.registry.web.jetty.working.directory=${nifi.registry.jetty.work.dir}
+nifi.registry.web.jetty.threads=${nifi.registry.web.jetty.threads}
+
+# security properties #
+nifi.registry.security.keystore=${nifi.registry.security.keystore}
+nifi.registry.security.keystoreType=${nifi.registry.security.keystoreType}
+nifi.registry.security.keystorePasswd=${nifi.registry.security.keystorePasswd}
+nifi.registry.security.keyPasswd=${nifi.registry.security.keyPasswd}
+nifi.registry.security.truststore=${nifi.registry.security.truststore}
+nifi.registry.security.truststoreType=${nifi.registry.security.truststoreType}
+nifi.registry.security.truststorePasswd=${nifi.registry.security.truststorePasswd}
+nifi.registry.security.needClientAuth=${nifi.registry.security.needClientAuth}
+nifi.registry.security.authorizers.configuration.file=${nifi.registry.security.authorizers.configuration.file}
+nifi.registry.security.authorizer=${nifi.registry.security.authorizer}
+nifi.registry.security.identity.providers.configuration.file=${nifi.registry.security.identity.providers.configuration.file}
+nifi.registry.security.identity.provider=${nifi.registry.security.identity.provider}
+
+# sensitive property protection properties #
+# nifi.registry.sensitive.props.additional.keys=
+
+# providers properties #
+nifi.registry.providers.configuration.file=${nifi.registry.providers.configuration.file}
+
+# legacy database properties, used to migrate data from original DB to new DB below
+# NOTE: Users upgrading from 0.1.0 should leave these populated, but new installs after 0.1.0 should leave these empty
+nifi.registry.db.directory=${nifi.registry.db.directory}
+nifi.registry.db.url.append=${nifi.registry.db.url.append}
+
+# database properties
+nifi.registry.db.url=${nifi.registry.db.url}
+nifi.registry.db.driver.class=${nifi.registry.db.driver.class}
+nifi.registry.db.driver.directory=${nifi.registry.db.driver.directory}
+nifi.registry.db.username=${nifi.registry.db.username}
+nifi.registry.db.password=${nifi.registry.db.password}
+nifi.registry.db.maxConnections=${nifi.registry.db.maxConnections}
+nifi.registry.db.sql.debug=${nifi.registry.db.sql.debug}
+
+# extension directories #
+# Each property beginning with "nifi.registry.extension.dir." will be treated as location for an extension,
+# and a class loader will be created for each location, with the system class loader as the parent
+#
+#nifi.registry.extension.dir.1=/path/to/extension1
+#nifi.registry.extension.dir.2=/path/to/extension2
+
+# Identity Mapping Properties #
+# These properties allow normalizing user identities such that identities coming from different identity providers
+# (certificates, LDAP, Kerberos) can be treated the same internally in NiFi. The following example demonstrates normalizing
+# DNs from certificates and principals from Kerberos into a common identity string:
+#
+# nifi.registry.security.identity.mapping.pattern.dn=^CN=(.*?), OU=(.*?), O=(.*?), L=(.*?), ST=(.*?), C=(.*?)$
+# nifi.registry.security.identity.mapping.value.dn=$1@$2
+# nifi.registry.security.identity.mapping.pattern.kerb=^(.*?)/instance@(.*?)$
+# nifi.registry.security.identity.mapping.value.kerb=$1@$2
+
+# kerberos properties #
+nifi.registry.kerberos.krb5.file=${nifi.registry.kerberos.krb5.file}
+nifi.registry.kerberos.spnego.principal=${nifi.registry.kerberos.spnego.principal}
+nifi.registry.kerberos.spnego.keytab.location=${nifi.registry.kerberos.spnego.keytab.location}
+nifi.registry.kerberos.spnego.authentication.expiration=${nifi.registry.kerberos.spnego.authentication.expiration}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/providers.xml
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/providers.xml b/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/providers.xml
new file mode 100644
index 0000000..faf8d4f
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/providers.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ 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.
+-->
+<providers>
+
+ <flowPersistenceProvider>
+ <class>org.apache.nifi.registry.provider.flow.FileSystemFlowPersistenceProvider</class>
+ <property name="Flow Storage Directory">./flow_storage</property>
+ </flowPersistenceProvider>
+
+ <!--
+ <flowPersistenceProvider>
+ <class>org.apache.nifi.registry.provider.flow.git.GitFlowPersistenceProvider</class>
+ <property name="Flow Storage Directory">./flow_storage</property>
+ <property name="Remote To Push"></property>
+ <property name="Remote Access User"></property>
+ <property name="Remote Access Password"></property>
+ </flowPersistenceProvider>
+ -->
+
+ <!--
+ <eventHookProvider>
+ <class>org.apache.nifi.registry.provider.hook.ScriptEventHookProvider</class>
+ <property name="Script Path"></property>
+ <property name="Working Directory"></property>
+ -->
+ <!-- Optional Whitelist Event types
+ <property name="Whitelisted Event Type 1">CREATE_FLOW</property>
+ <property name="Whitelisted Event Type 2">DELETE_FLOW</property>
+ -->
+ <!--
+ </eventHookProvider>
+ -->
+
+ <!-- This will log all events to a separate file specified by the EVENT_APPENDER in logback.xml -->
+ <!--
+ <eventHookProvider>
+ <class>org.apache.nifi.registry.provider.hook.LoggingEventHookProvider</class>
+ </eventHookProvider>
+ -->
+
+</providers>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-runtime/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-runtime/pom.xml b/nifi-registry-core/nifi-registry-runtime/pom.xml
new file mode 100644
index 0000000..ed0fae4
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-runtime/pom.xml
@@ -0,0 +1,46 @@
+<?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>
+ <groupId>org.apache.nifi.registry</groupId>
+ <artifactId>nifi-registry-core</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>nifi-registry-runtime</artifactId>
+ <packaging>jar</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.nifi.registry</groupId>
+ <artifactId>nifi-registry-utils</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.nifi.registry</groupId>
+ <artifactId>nifi-registry-properties</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.nifi.registry</groupId>
+ <artifactId>nifi-registry-jetty</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jul-to-slf4j</artifactId>
+ </dependency>
+ </dependencies>
+</project>
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-runtime/src/main/java/org/apache/nifi/registry/BootstrapListener.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-runtime/src/main/java/org/apache/nifi/registry/BootstrapListener.java b/nifi-registry-core/nifi-registry-runtime/src/main/java/org/apache/nifi/registry/BootstrapListener.java
new file mode 100644
index 0000000..0eabe94
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-runtime/src/main/java/org/apache/nifi/registry/BootstrapListener.java
@@ -0,0 +1,395 @@
+/*
+ * 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.registry;
+
+import org.apache.nifi.registry.util.LimitingInputStream;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.lang.management.LockInfo;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MonitorInfo;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+public class BootstrapListener {
+
+ private static final Logger logger = LoggerFactory.getLogger(BootstrapListener.class);
+
+ private final NiFiRegistry nifi;
+ private final int bootstrapPort;
+ private final String secretKey;
+
+ private volatile Listener listener;
+ private volatile ServerSocket serverSocket;
+
+ public BootstrapListener(final NiFiRegistry nifi, final int bootstrapPort) {
+ this.nifi = nifi;
+ this.bootstrapPort = bootstrapPort;
+ secretKey = UUID.randomUUID().toString();
+ }
+
+ public void start() throws IOException {
+ logger.debug("Starting Bootstrap Listener to communicate with Bootstrap Port {}", bootstrapPort);
+
+ serverSocket = new ServerSocket();
+ serverSocket.bind(new InetSocketAddress("localhost", 0));
+ serverSocket.setSoTimeout(2000);
+
+ final int localPort = serverSocket.getLocalPort();
+ logger.info("Started Bootstrap Listener, Listening for incoming requests on port {}", localPort);
+
+ listener = new Listener(serverSocket);
+ final Thread listenThread = new Thread(listener);
+ listenThread.setDaemon(true);
+ listenThread.setName("Listen to Bootstrap");
+ listenThread.start();
+
+ logger.debug("Notifying Bootstrap that local port is {}", localPort);
+ sendCommand("PORT", new String[] { String.valueOf(localPort), secretKey});
+ }
+
+ public void stop() {
+ if (listener != null) {
+ listener.stop();
+ }
+ }
+
+ public void sendStartedStatus(boolean status) throws IOException {
+ logger.debug("Notifying Bootstrap that the status of starting NiFi Registry is {}", status);
+ sendCommand("STARTED", new String[]{ String.valueOf(status) });
+ }
+
+ private void sendCommand(final String command, final String[] args) throws IOException {
+ try (final Socket socket = new Socket()) {
+ socket.setSoTimeout(60000);
+ socket.connect(new InetSocketAddress("localhost", bootstrapPort));
+ socket.setSoTimeout(60000);
+
+ final StringBuilder commandBuilder = new StringBuilder(command);
+ for (final String arg : args) {
+ commandBuilder.append(" ").append(arg);
+ }
+ commandBuilder.append("\n");
+
+ final String commandWithArgs = commandBuilder.toString();
+ logger.debug("Sending command to Bootstrap: " + commandWithArgs);
+
+ final OutputStream out = socket.getOutputStream();
+ out.write((commandWithArgs).getBytes(StandardCharsets.UTF_8));
+ out.flush();
+
+ logger.debug("Awaiting response from Bootstrap...");
+ final BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+ final String response = reader.readLine();
+ if ("OK".equals(response)) {
+ logger.info("Successfully initiated communication with Bootstrap");
+ } else {
+ logger.error("Failed to communicate with Bootstrap. Bootstrap may be unable to issue or receive commands from NiFi Registry ");
+ }
+ }
+ }
+
+ private class Listener implements Runnable {
+
+ private final ServerSocket serverSocket;
+ private final ExecutorService executor;
+ private volatile boolean stopped = false;
+
+ public Listener(final ServerSocket serverSocket) {
+ this.serverSocket = serverSocket;
+ this.executor = Executors.newFixedThreadPool(2);
+ }
+
+ public void stop() {
+ stopped = true;
+
+ executor.shutdownNow();
+
+ try {
+ serverSocket.close();
+ } catch (final IOException ioe) {
+ // nothing to really do here. we could log this, but it would just become
+ // confusing in the logs, as we're shutting down and there's no real benefit
+ }
+ }
+
+ @Override
+ public void run() {
+ while (!stopped) {
+ try {
+ final Socket socket;
+ try {
+ logger.debug("Listening for Bootstrap Requests");
+ socket = serverSocket.accept();
+ } catch (final SocketTimeoutException ste) {
+ if (stopped) {
+ return;
+ }
+
+ continue;
+ } catch (final IOException ioe) {
+ if (stopped) {
+ return;
+ }
+
+ throw ioe;
+ }
+
+ logger.debug("Received connection from Bootstrap");
+ socket.setSoTimeout(5000);
+
+ executor.submit(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ final BootstrapRequest request = readRequest(socket.getInputStream());
+ final BootstrapRequest.RequestType requestType = request.getRequestType();
+
+ switch (requestType) {
+ case PING:
+ logger.debug("Received PING request from Bootstrap; responding");
+ echoPing(socket.getOutputStream());
+ logger.debug("Responded to PING request from Bootstrap");
+ break;
+ case SHUTDOWN:
+ logger.info("Received SHUTDOWN request from Bootstrap");
+ echoShutdown(socket.getOutputStream());
+ nifi.shutdownHook();
+ return;
+ case DUMP:
+ logger.info("Received DUMP request from Bootstrap");
+ writeDump(socket.getOutputStream());
+ break;
+ }
+ } catch (final Throwable t) {
+ logger.error("Failed to process request from Bootstrap due to " + t.toString(), t);
+ } finally {
+ try {
+ socket.close();
+ } catch (final IOException ioe) {
+ logger.warn("Failed to close socket to Bootstrap due to {}", ioe.toString());
+ }
+ }
+ }
+ });
+ } catch (final Throwable t) {
+ logger.error("Failed to process request from Bootstrap due to " + t.toString(), t);
+ }
+ }
+ }
+ }
+
+ private static void writeDump(final OutputStream out) throws IOException {
+ final ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
+ final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
+
+ final ThreadInfo[] infos = mbean.dumpAllThreads(true, true);
+ final long[] deadlockedThreadIds = mbean.findDeadlockedThreads();
+ final long[] monitorDeadlockThreadIds = mbean.findMonitorDeadlockedThreads();
+
+ final List<ThreadInfo> sortedInfos = new ArrayList<>(infos.length);
+ for (final ThreadInfo info : infos) {
+ sortedInfos.add(info);
+ }
+ Collections.sort(sortedInfos, new Comparator<ThreadInfo>() {
+ @Override
+ public int compare(ThreadInfo o1, ThreadInfo o2) {
+ return o1.getThreadName().toLowerCase().compareTo(o2.getThreadName().toLowerCase());
+ }
+ });
+
+ final StringBuilder sb = new StringBuilder();
+ for (final ThreadInfo info : sortedInfos) {
+ sb.append("\n");
+ sb.append("\"").append(info.getThreadName()).append("\" Id=");
+ sb.append(info.getThreadId()).append(" ");
+ sb.append(info.getThreadState().toString()).append(" ");
+
+ switch (info.getThreadState()) {
+ case BLOCKED:
+ case TIMED_WAITING:
+ case WAITING:
+ sb.append(" on ");
+ sb.append(info.getLockInfo());
+ break;
+ default:
+ break;
+ }
+
+ if (info.isSuspended()) {
+ sb.append(" (suspended)");
+ }
+ if (info.isInNative()) {
+ sb.append(" (in native code)");
+ }
+
+ if (deadlockedThreadIds != null && deadlockedThreadIds.length > 0) {
+ for (final long id : deadlockedThreadIds) {
+ if (id == info.getThreadId()) {
+ sb.append(" ** DEADLOCKED THREAD **");
+ }
+ }
+ }
+
+ if (monitorDeadlockThreadIds != null && monitorDeadlockThreadIds.length > 0) {
+ for (final long id : monitorDeadlockThreadIds) {
+ if (id == info.getThreadId()) {
+ sb.append(" ** MONITOR-DEADLOCKED THREAD **");
+ }
+ }
+ }
+
+ final StackTraceElement[] stackTraces = info.getStackTrace();
+ for (final StackTraceElement element : stackTraces) {
+ sb.append("\n\tat ").append(element);
+
+ final MonitorInfo[] monitors = info.getLockedMonitors();
+ for (final MonitorInfo monitor : monitors) {
+ if (monitor.getLockedStackFrame().equals(element)) {
+ sb.append("\n\t- waiting on ").append(monitor);
+ }
+ }
+ }
+
+ final LockInfo[] lockInfos = info.getLockedSynchronizers();
+ if (lockInfos.length > 0) {
+ sb.append("\n\t");
+ sb.append("Number of Locked Synchronizers: ").append(lockInfos.length);
+ for (final LockInfo lockInfo : lockInfos) {
+ sb.append("\n\t- ").append(lockInfo.toString());
+ }
+ }
+
+ sb.append("\n");
+ }
+
+ if (deadlockedThreadIds != null && deadlockedThreadIds.length > 0) {
+ sb.append("\n\nDEADLOCK DETECTED!");
+ sb.append("\nThe following thread IDs are deadlocked:");
+ for (final long id : deadlockedThreadIds) {
+ sb.append("\n").append(id);
+ }
+ }
+
+ if (monitorDeadlockThreadIds != null && monitorDeadlockThreadIds.length > 0) {
+ sb.append("\n\nMONITOR DEADLOCK DETECTED!");
+ sb.append("\nThe following thread IDs are deadlocked:");
+ for (final long id : monitorDeadlockThreadIds) {
+ sb.append("\n").append(id);
+ }
+ }
+
+ writer.write(sb.toString());
+ writer.flush();
+ }
+
+ private void echoPing(final OutputStream out) throws IOException {
+ out.write("PING\n".getBytes(StandardCharsets.UTF_8));
+ out.flush();
+ }
+
+ private void echoShutdown(final OutputStream out) throws IOException {
+ out.write("SHUTDOWN\n".getBytes(StandardCharsets.UTF_8));
+ out.flush();
+ }
+
+ @SuppressWarnings("resource") // we don't want to close the stream, as the caller will do that
+ private BootstrapRequest readRequest(final InputStream in) throws IOException {
+ // We want to ensure that we don't try to read data from an InputStream directly
+ // by a BufferedReader because any user on the system could open a socket and send
+ // a multi-gigabyte file without any new lines in order to crash the NiFi instance
+ // (or at least cause OutOfMemoryErrors, which can wreak havoc on the running instance).
+ // So we will limit the Input Stream to only 4 KB, which should be plenty for any request.
+ final LimitingInputStream limitingIn = new LimitingInputStream(in, 4096);
+ final BufferedReader reader = new BufferedReader(new InputStreamReader(limitingIn));
+
+ final String line = reader.readLine();
+ final String[] splits = line.split(" ");
+ if (splits.length < 1) {
+ throw new IOException("Received invalid request from Bootstrap: " + line);
+ }
+
+ final String requestType = splits[0];
+ final String[] args;
+ if (splits.length == 1) {
+ throw new IOException("Received invalid request from Bootstrap; request did not have a secret key; request type = " + requestType);
+ } else if (splits.length == 2) {
+ args = new String[0];
+ } else {
+ args = Arrays.copyOfRange(splits, 2, splits.length);
+ }
+
+ final String requestKey = splits[1];
+ if (!secretKey.equals(requestKey)) {
+ throw new IOException("Received invalid Secret Key for request type " + requestType);
+ }
+
+ try {
+ return new BootstrapRequest(requestType, args);
+ } catch (final Exception e) {
+ throw new IOException("Received invalid request from Bootstrap; request type = " + requestType);
+ }
+ }
+
+ private static class BootstrapRequest {
+
+ public static enum RequestType {
+
+ SHUTDOWN,
+ DUMP,
+ PING;
+ }
+
+ private final RequestType requestType;
+ private final String[] args;
+
+ public BootstrapRequest(final String request, final String[] args) {
+ this.requestType = RequestType.valueOf(request);
+ this.args = args;
+ }
+
+ public RequestType getRequestType() {
+ return requestType;
+ }
+
+ @SuppressWarnings("unused")
+ public String[] getArgs() {
+ return args;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-runtime/src/main/java/org/apache/nifi/registry/NiFiRegistry.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-runtime/src/main/java/org/apache/nifi/registry/NiFiRegistry.java b/nifi-registry-core/nifi-registry-runtime/src/main/java/org/apache/nifi/registry/NiFiRegistry.java
new file mode 100644
index 0000000..65fdcf4
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-runtime/src/main/java/org/apache/nifi/registry/NiFiRegistry.java
@@ -0,0 +1,197 @@
+/*
+ * 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.registry;
+
+import org.apache.nifi.registry.jetty.JettyServer;
+import org.apache.nifi.registry.properties.NiFiRegistryProperties;
+import org.apache.nifi.registry.properties.NiFiRegistryPropertiesLoader;
+import org.apache.nifi.registry.properties.SensitivePropertyProtectionException;
+import org.apache.nifi.registry.security.crypto.BootstrapFileCryptoKeyProvider;
+import org.apache.nifi.registry.security.crypto.CryptoKeyProvider;
+import org.apache.nifi.registry.security.crypto.MissingCryptoKeyException;
+import org.apache.nifi.registry.util.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.bridge.SLF4JBridgeHandler;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Main entry point for NiFiRegistry.
+ */
+public class NiFiRegistry {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(NiFiRegistry.class);
+
+ public static final String BOOTSTRAP_PORT_PROPERTY = "nifi.registry.bootstrap.listen.port";
+
+ public static final String NIFI_REGISTRY_PROPERTIES_FILE_PATH_PROPERTY = "nifi.registry.properties.file.path";
+ public static final String NIFI_REGISTRY_BOOTSTRAP_FILE_PATH_PROPERTY = "nifi.registry.bootstrap.config.file.path";
+
+ public static final String RELATIVE_BOOTSTRAP_FILE_LOCATION = "conf/bootstrap.conf";
+ public static final String RELATIVE_PROPERTIES_FILE_LOCATION = "conf/nifi-registry.properties";
+
+ private final JettyServer server;
+ private final BootstrapListener bootstrapListener;
+ private volatile boolean shutdown = false;
+
+ public NiFiRegistry(final NiFiRegistryProperties properties, CryptoKeyProvider masterKeyProvider)
+ throws ClassNotFoundException, IOException, NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+
+ Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
+ @Override
+ public void uncaughtException(final Thread t, final Throwable e) {
+ LOGGER.error("An Unknown Error Occurred in Thread {}: {}", t, e.toString());
+ LOGGER.error("", e);
+ }
+ });
+
+ // register the shutdown hook
+ Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
+ @Override
+ public void run() {
+ // shutdown the jetty server
+ shutdownHook();
+ }
+ }));
+
+ final String bootstrapPort = System.getProperty(BOOTSTRAP_PORT_PROPERTY);
+ if (bootstrapPort != null) {
+ try {
+ final int port = Integer.parseInt(bootstrapPort);
+
+ if (port < 1 || port > 65535) {
+ throw new RuntimeException("Failed to start NiFi Registry because system property '" + BOOTSTRAP_PORT_PROPERTY + "' is not a valid integer in the range 1 - 65535");
+ }
+
+ bootstrapListener = new BootstrapListener(this, port);
+ bootstrapListener.start();
+ } catch (final NumberFormatException nfe) {
+ throw new RuntimeException("Failed to start NiFi Registry because system property '" + BOOTSTRAP_PORT_PROPERTY + "' is not a valid integer in the range 1 - 65535");
+ }
+ } else {
+ LOGGER.info("NiFi Registry started without Bootstrap Port information provided; will not listen for requests from Bootstrap");
+ bootstrapListener = null;
+ }
+
+ // delete the web working dir - if the application does not start successfully
+ // the web app directories might be in an invalid state. when this happens
+ // jetty will not attempt to re-extract the war into the directory. by removing
+ // the working directory, we can be assured that it will attempt to extract the
+ // war every time the application starts.
+ File webWorkingDir = properties.getWebWorkingDirectory();
+ FileUtils.deleteFilesInDirectory(webWorkingDir, null, LOGGER, true, true);
+ FileUtils.deleteFile(webWorkingDir, LOGGER, 3);
+
+ // redirect JUL log events
+ SLF4JBridgeHandler.removeHandlersForRootLogger();
+ SLF4JBridgeHandler.install();
+
+ final long startTime = System.nanoTime();
+ server = new JettyServer(properties, masterKeyProvider);
+
+ if (shutdown) {
+ LOGGER.info("NiFi Registry has been shutdown via NiFi Registry Bootstrap. Will not start Controller");
+ } else {
+ server.start();
+
+ if (bootstrapListener != null) {
+ bootstrapListener.sendStartedStatus(true);
+ }
+
+ final long duration = System.nanoTime() - startTime;
+ LOGGER.info("Registry initialization took " + duration + " nanoseconds "
+ + "(" + (int) TimeUnit.SECONDS.convert(duration, TimeUnit.NANOSECONDS) + " seconds).");
+ }
+ }
+
+ protected void shutdownHook() {
+ try {
+ this.shutdown = true;
+
+ LOGGER.info("Initiating shutdown of Jetty web server...");
+ if (server != null) {
+ server.stop();
+ }
+ if (bootstrapListener != null) {
+ bootstrapListener.stop();
+ }
+ LOGGER.info("Jetty web server shutdown completed (nicely or otherwise).");
+ } catch (final Throwable t) {
+ LOGGER.warn("Problem occurred ensuring Jetty web server was properly terminated due to " + t);
+ }
+ }
+
+ /**
+ * Main entry point of the application.
+ *
+ * @param args things which are ignored
+ */
+ public static void main(String[] args) {
+ LOGGER.info("Launching NiFi Registry...");
+
+ final CryptoKeyProvider masterKeyProvider;
+ final NiFiRegistryProperties properties;
+ try {
+ final String bootstrapConfigFilePath = System.getProperty(NIFI_REGISTRY_BOOTSTRAP_FILE_PATH_PROPERTY, RELATIVE_BOOTSTRAP_FILE_LOCATION);
+ masterKeyProvider = new BootstrapFileCryptoKeyProvider(bootstrapConfigFilePath);
+ LOGGER.info("Read property protection key from {}", bootstrapConfigFilePath);
+ properties = initializeProperties(masterKeyProvider);
+ } catch (final IllegalArgumentException iae) {
+ throw new RuntimeException("Unable to load properties: " + iae, iae);
+ }
+
+ try {
+ new NiFiRegistry(properties, masterKeyProvider);
+ } catch (final Throwable t) {
+ LOGGER.error("Failure to launch NiFi Registry due to " + t, t);
+ }
+ }
+
+ private static NiFiRegistryProperties initializeProperties(CryptoKeyProvider masterKeyProvider) {
+
+ String key = CryptoKeyProvider.EMPTY_KEY;
+ try {
+ key = masterKeyProvider.getKey();
+ } catch (MissingCryptoKeyException e) {
+ LOGGER.debug("CryptoKeyProvider provided to initializeProperties method was empty - did not contain a key.");
+ // Do nothing. The key can be empty when it is passed to the loader as the loader will only use it if any properties are protected.
+ }
+
+ try {
+ try {
+ // Load properties using key. If properties are protected and key missing, throw RuntimeException
+ final String nifiRegistryPropertiesFilePath = System.getProperty(NIFI_REGISTRY_PROPERTIES_FILE_PATH_PROPERTY, RELATIVE_PROPERTIES_FILE_LOCATION);
+ final NiFiRegistryProperties properties = NiFiRegistryPropertiesLoader.withKey(key).load(nifiRegistryPropertiesFilePath);
+ LOGGER.info("Loaded {} properties", properties.size());
+ return properties;
+ } catch (SensitivePropertyProtectionException e) {
+ final String msg = "There was an issue decrypting protected properties";
+ LOGGER.error(msg, e);
+ throw new IllegalArgumentException(msg);
+ }
+ } catch (IllegalArgumentException e) {
+ final String msg = "The bootstrap process did not provide a valid key and there are protected properties present in the properties file";
+ LOGGER.error(msg, e);
+ throw new IllegalArgumentException(msg);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-runtime/src/main/java/org/apache/nifi/registry/util/LimitingInputStream.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-runtime/src/main/java/org/apache/nifi/registry/util/LimitingInputStream.java b/nifi-registry-core/nifi-registry-runtime/src/main/java/org/apache/nifi/registry/util/LimitingInputStream.java
new file mode 100644
index 0000000..c069ec2
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-runtime/src/main/java/org/apache/nifi/registry/util/LimitingInputStream.java
@@ -0,0 +1,107 @@
+/*
+ * 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.registry.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class LimitingInputStream extends InputStream {
+
+ private final InputStream in;
+ private final long limit;
+ private long bytesRead = 0;
+
+ public LimitingInputStream(final InputStream in, final long limit) {
+ this.in = in;
+ this.limit = limit;
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (bytesRead >= limit) {
+ return -1;
+ }
+
+ final int val = in.read();
+ if (val > -1) {
+ bytesRead++;
+ }
+ return val;
+ }
+
+ @Override
+ public int read(final byte[] b) throws IOException {
+ if (bytesRead >= limit) {
+ return -1;
+ }
+
+ final int maxToRead = (int) Math.min(b.length, limit - bytesRead);
+
+ final int val = in.read(b, 0, maxToRead);
+ if (val > 0) {
+ bytesRead += val;
+ }
+ return val;
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (bytesRead >= limit) {
+ return -1;
+ }
+
+ final int maxToRead = (int) Math.min(len, limit - bytesRead);
+
+ final int val = in.read(b, off, maxToRead);
+ if (val > 0) {
+ bytesRead += val;
+ }
+ return val;
+ }
+
+ @Override
+ public long skip(final long n) throws IOException {
+ final long skipped = in.skip(Math.min(n, limit - bytesRead));
+ bytesRead += skipped;
+ return skipped;
+ }
+
+ @Override
+ public int available() throws IOException {
+ return in.available();
+ }
+
+ @Override
+ public void close() throws IOException {
+ in.close();
+ }
+
+ @Override
+ public void mark(int readlimit) {
+ in.mark(readlimit);
+ }
+
+ @Override
+ public boolean markSupported() {
+ return in.markSupported();
+ }
+
+ @Override
+ public void reset() throws IOException {
+ in.reset();
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-security-api/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-security-api/pom.xml b/nifi-registry-core/nifi-registry-security-api/pom.xml
new file mode 100644
index 0000000..5100569
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-security-api/pom.xml
@@ -0,0 +1,41 @@
+<?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">
+ <parent>
+ <artifactId>nifi-registry-core</artifactId>
+ <groupId>org.apache.nifi.registry</groupId>
+ <version>0.3.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>nifi-registry-security-api</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.nifi.registry</groupId>
+ <artifactId>nifi-registry-utils</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>3.1.0</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+</project>
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/security/authentication/AuthenticationRequest.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/security/authentication/AuthenticationRequest.java b/nifi-registry-core/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/security/authentication/AuthenticationRequest.java
new file mode 100644
index 0000000..72ae50e
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/security/authentication/AuthenticationRequest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.registry.security.authentication;
+
+import java.io.Serializable;
+
+public class AuthenticationRequest implements Serializable {
+
+ private String username;
+ private Object credentials;
+ private Object details;
+
+ public AuthenticationRequest(String username, Object credentials, Object details) {
+ this.username = username;
+ this.credentials = credentials;
+ this.details = details;
+ }
+
+ public AuthenticationRequest() {}
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public Object getCredentials() {
+ return credentials;
+ }
+
+ public void setCredentials(Object credentials) {
+ this.credentials = credentials;
+ }
+
+ public Object getDetails() {
+ return details;
+ }
+
+ public void setDetails(Object details) {
+ this.details = details;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ AuthenticationRequest that = (AuthenticationRequest) o;
+
+ return username != null ? username.equals(that.username) : that.username == null;
+ }
+
+ @Override
+ public int hashCode() {
+ return username != null ? username.hashCode() : 0;
+ }
+
+ @Override
+ public String toString() {
+ return "AuthenticationRequest{" +
+ "username='" + username + '\'' +
+ ", credentials=[PROTECTED]" +
+ ", details=" + details +
+ '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/security/authentication/AuthenticationResponse.java
----------------------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/security/authentication/AuthenticationResponse.java b/nifi-registry-core/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/security/authentication/AuthenticationResponse.java
new file mode 100644
index 0000000..b8eb721
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/security/authentication/AuthenticationResponse.java
@@ -0,0 +1,98 @@
+/*
+ * 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.registry.security.authentication;
+
+import java.io.Serializable;
+
+/**
+ * Authentication response for a user login attempt.
+ */
+public class AuthenticationResponse implements Serializable {
+
+ private final String identity;
+ private final String username;
+ private final long expiration;
+ private final String issuer;
+
+ /**
+ * Creates an authentication response. The username and how long the authentication is valid in milliseconds
+ *
+ * @param identity The user identity
+ * @param username The username
+ * @param expiration The expiration in milliseconds
+ * @param issuer The issuer of the token
+ */
+ public AuthenticationResponse(final String identity, final String username, final long expiration, final String issuer) {
+ this.identity = identity;
+ this.username = username;
+ this.expiration = expiration;
+ this.issuer = issuer;
+ }
+
+ public String getIdentity() {
+ return identity;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getIssuer() {
+ return issuer;
+ }
+
+ /**
+ * Returns the expiration of a given authentication in milliseconds.
+ *
+ * @return The expiration in milliseconds
+ */
+ public long getExpiration() {
+ return expiration;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ AuthenticationResponse that = (AuthenticationResponse) o;
+
+ if (expiration != that.expiration) return false;
+ if (identity != null ? !identity.equals(that.identity) : that.identity != null) return false;
+ if (username != null ? !username.equals(that.username) : that.username != null) return false;
+ return issuer != null ? issuer.equals(that.issuer) : that.issuer == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = identity != null ? identity.hashCode() : 0;
+ result = 31 * result + (username != null ? username.hashCode() : 0);
+ result = 31 * result + (int) (expiration ^ (expiration >>> 32));
+ result = 31 * result + (issuer != null ? issuer.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "AuthenticationResponse{" +
+ "identity='" + identity + '\'' +
+ ", username='" + username + '\'' +
+ ", expiration=" + expiration +
+ ", issuer='" + issuer + '\'' +
+ '}';
+ }
+}