Author: tkurc
Date: Wed Feb 17 02:15:29 2016
New Revision: 1730775

URL: http://svn.apache.org/viewvc?rev=1730775&view=rev
Log:
NIFI-1379: Updating docs

Added:
    nifi/site/trunk/docs/nifi-docs/html/images/allow-weak-crypto.png   (with 
props)
    nifi/site/trunk/docs/nifi-docs/html/images/bcrypt-salt.png   (with props)
    nifi/site/trunk/docs/nifi-docs/html/images/iconDetails.png   (with props)
    nifi/site/trunk/docs/nifi-docs/html/images/nifi-connection-bend-points.png  
 (with props)
    nifi/site/trunk/docs/nifi-docs/html/images/nifi-legacy-salt.png   (with 
props)
    nifi/site/trunk/docs/nifi-docs/html/images/openssl-salt.png   (with props)
    nifi/site/trunk/docs/nifi-docs/html/images/pbkdf2-salt.png   (with props)
    nifi/site/trunk/docs/nifi-docs/html/images/scrypt-salt.png   (with props)
Modified:
    nifi/site/trunk/docs/nifi-docs/html/administration-guide.html
    nifi/site/trunk/docs/nifi-docs/html/developer-guide.html
    nifi/site/trunk/docs/nifi-docs/html/expression-language-guide.html
    nifi/site/trunk/docs/nifi-docs/html/getting-started.html
    nifi/site/trunk/docs/nifi-docs/html/overview.html
    nifi/site/trunk/docs/nifi-docs/html/user-guide.html

Modified: nifi/site/trunk/docs/nifi-docs/html/administration-guide.html
URL: 
http://svn.apache.org/viewvc/nifi/site/trunk/docs/nifi-docs/html/administration-guide.html?rev=1730775&r1=1730774&r2=1730775&view=diff
==============================================================================
--- nifi/site/trunk/docs/nifi-docs/html/administration-guide.html (original)
+++ nifi/site/trunk/docs/nifi-docs/html/administration-guide.html Wed Feb 17 
02:15:29 2016
@@ -461,7 +461,23 @@ body.book #toc,body.book #preamble,body.
 <li><a href="#security-configuration">Security Configuration</a></li>
 <li><a href="#user-authentication">User Authentication</a></li>
 <li><a href="#controlling-levels-of-access">Controlling Levels of 
Access</a></li>
+<li><a href="#encryption">Encryption Configuration</a>
+<ul class="sectlevel2">
+<li><a href="#key-derivation-functions">Key Derivation Functions</a></li>
+<li><a href="#salt-and-iv-encoding">Salt and IV Encoding</a></li>
+<li><a 
href="#java-cryptography-extension-jce-limited-strength-jurisdiction-policies">Java
 Cryptography Extension (JCE) Limited Strength Jurisdiction Policies</a></li>
+<li><a href="#allow-insecure-cryptographic-modes">Allow Insecure Cryptographic 
Modes</a></li>
+</ul>
+</li>
 <li><a href="#clustering">Clustering Configuration</a></li>
+<li><a href="#state_management">State Management</a>
+<ul class="sectlevel2">
+<li><a href="#state_providers">Configuring State Providers</a></li>
+<li><a href="#embedded_zookeeper">Embedded ZooKeeper Server</a></li>
+<li><a href="#zk_access_control">ZooKeeper Access Control</a></li>
+<li><a href="#securing_zookeeper">Securing ZooKeeper</a></li>
+</ul>
+</li>
 <li><a href="#bootstrap_properties">Bootstrap Properties</a></li>
 <li><a href="#notification_services">Notification Services</a></li>
 <li><a href="#system_properties">System Properties</a></li>
@@ -521,7 +537,13 @@ body.book #toc,body.book #preamble,body.
 </ul>
 </div>
 <div class="paragraph">
-<p>Note that there is a known issue in Internet Explorer (IE) 10 and 11 that 
can cause problems when moving items on the NiFi graph. If you encounter this 
problem, we suggest using a browser other than IE. This known issue is 
described here: <a 
href="https://connect.microsoft.com/IE/Feedback/Details/1050422"; 
class="bare">https://connect.microsoft.com/IE/Feedback/Details/1050422</a>.</p>
+<p><strong>Note</strong> There is a known issue in Internet Explorer (IE) 10 
and 11 that can cause problems when moving items on the NiFi graph. If you 
encounter this problem, we suggest using a browser other than IE. This known 
issue is described here: <a 
href="https://connect.microsoft.com/IE/Feedback/Details/1050422"; 
class="bare">https://connect.microsoft.com/IE/Feedback/Details/1050422</a>.</p>
+</div>
+<div class="paragraph">
+<p><strong>Note</strong> Java 7 default perm gen sizing can result in <em>out 
of memory errors</em> due to the amount of classes loaded by NiFi.  See the <a 
href="#bootstrap_properties">Bootstrap Properties</a> section for more 
information.</p>
+</div>
+<div class="paragraph">
+<p><strong>Note</strong> Under sustained and extremely high throughput the 
CodeCache settings may need to be tuned to avoid sudden performance loss.  See 
the <a href="#bootstrap_properties">Bootstrap Properties</a> section for more 
information.</p>
 </div>
 </div>
 </div>
@@ -1170,6 +1192,399 @@ cluster, s/he can grant it to the group
 </div>
 </div>
 <div class="sect1">
+<h2 id="encryption"><a class="anchor" href="#encryption"></a>Encryption 
Configuration</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>This section provides an overview of the capabilities of NiFi to encrypt 
and decrypt data.</p>
+</div>
+<div class="paragraph">
+<p>The <code>EncryptContent</code> processor allows for the encryption and 
decryption of data, both internal to NiFi and integrated with external systems, 
such as <code>openssl</code> and other data sources and consumers.</p>
+</div>
+<div class="sect2">
+<h3 id="key-derivation-functions"><a class="anchor" 
href="#key-derivation-functions"></a>Key Derivation Functions</h3>
+<div class="paragraph">
+<p>Key Derivation Functions (KDF) are mechanisms by which human-readable 
information, usually a password or other secret information, is translated into 
a cryptographic key suitable for data protection. For further information, read 
<a href="https://en.wikipedia.org/wiki/Key_derivation_function";>the Wikipedia 
entry on Key Derivation Functions</a>.
+Currently, KDFs are ingested by <code>CipherProvider</code> implementations 
and return a fully-initialized <code>Cipher</code> object to be used for 
encryption or decryption. Due to the use of a 
<code>CipherProviderFactory</code>, the KDFs are not customizable at this time. 
Future enhancements will include the ability to provide custom cost parameters 
to the KDF at initialization time. As a work-around, 
<code>CipherProvider</code> instances can be initialized with custom cost 
parameters in the constructor but this is not currently supported by the 
<code>CipherProviderFactory</code>.
+Here are the KDFs currently supported by NiFi (primarily in the 
<code>EncryptContent</code> processor for password-based encryption (PBE)) and 
relevant notes:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>NiFi Legacy KDF</p>
+<div class="ulist">
+<ul>
+<li>
+<p>The original KDF used by NiFi for internal key derivation for PBE, this is 
1000 iterations of the MD5 digest over the concatenation of the password and 8 
or 16 bytes of random salt (the salt length depends on the selected cipher 
block size).</p>
+</li>
+<li>
+<p>This KDF is <strong>deprecated as of NiFi 0.5.0</strong> and should only be 
used for backwards compatibility to decrypt data that was previously encrypted 
by a legacy version of NiFi.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>OpenSSL PKCS#5 v1.5 EVP_BytesToKey</p>
+<div class="ulist">
+<ul>
+<li>
+<p>This KDF was added in v0.4.0.</p>
+</li>
+<li>
+<p>This KDF is provided for compatibility with data encrypted using 
OpenSSL&#8217;s default PBE, known as <code>EVP_BytesToKey</code>. This is a 
single iteration of MD5 over the concatenation of the password and 8 bytes of 
random ASCII salt. OpenSSL recommends using <code>PBKDF2</code> for key 
derivation but does not expose the library method necessary to the command-line 
tool, so this KDF is still the de facto default for command-line encryption.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>Bcrypt</p>
+<div class="ulist">
+<ul>
+<li>
+<p>This KDF was added in v0.5.0.</p>
+</li>
+<li>
+<p><a href="https://en.wikipedia.org/wiki/Bcrypt";>Bcrypt</a> is an adaptive 
function based on the <a 
href="https://en.wikipedia.org/wiki/Blowfish_(cipher)">Blowfish</a> cipher. 
This KDF is strongly recommended as it automatically incorporates a random 16 
byte salt, configurable cost parameter (or "work factor"), and is hardened 
against brute-force attacks using <a 
href="https://en.wikipedia.org/wiki/General-purpose_computing_on_graphics_processing_units";>GPGPU</a>
 (which share memory between cores) by requiring access to "large" blocks of 
memory during the key derivation. It is less resistant to <a 
href="https://en.wikipedia.org/wiki/Field-programmable_gate_array";>FPGA</a> 
brute-force attacks where the gate arrays have access to individual embedded 
RAM blocks.</p>
+</li>
+<li>
+<p>Because the length of a Bcrypt-derived key is always 184 bits, the complete 
output is then fed to a <code>SHA-512</code> digest and truncated to the 
desired key length. This provides the benefit of the avalanche effect on the 
formatted input.</p>
+</li>
+<li>
+<p>The recommended minimum work factor is 12 (2<sup>12</sup> key derivation 
rounds) (as of 2/1/2016 on commodity hardware) and should be increased to the 
threshold at which legitimate systems will encounter detrimental delays (see 
schedule below or use 
<code>BcryptCipherProviderGroovyTest#testDefaultConstructorShouldProvideStrongWorkFactor()</code>
 to calculate safe minimums).</p>
+</li>
+<li>
+<p>The salt format is <code>$2a$10$ABCDEFGHIJKLMNOPQRSTUV</code>. The salt is 
delimited by <code>$</code> and the three sections are as follows:</p>
+<div class="ulist">
+<ul>
+<li>
+<p><code>2a</code> - the version of the format. An extensive explanation can 
be found <a 
href="http://blog.ircmaxell.com/2012/12/seven-ways-to-screw-up-bcrypt.html";>here</a>.
 NiFi currently uses <code>2a</code> for all salts generated internally.</p>
+</li>
+<li>
+<p><code>10</code> - the work factor. This is actually the log<sub>2</sub> 
value, so the total iteration count would be 2<sup>10</sup> in this case.</p>
+</li>
+<li>
+<p><code>ABCDEFGHIJKLMNOPQRSTUV</code> - the 22 character, Base64-encoded, 
unpadded, raw salt value. This decodes to a 16 byte salt used in the key 
derivation.</p>
+</li>
+</ul>
+</div>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>Scrypt</p>
+<div class="ulist">
+<ul>
+<li>
+<p>This KDF was added in v0.5.0.</p>
+</li>
+<li>
+<p><a href="https://en.wikipedia.org/wiki/Scrypt";>Scrypt</a> is an adaptive 
function designed in response to <code>bcrypt</code>. This KDF is recommended 
as it requires relatively large amounts of memory for each derivation, making 
it resistant to hardware brute-force attacks.</p>
+</li>
+<li>
+<p>The recommended minimum cost is <code>N</code>=2<sup>14</sup>, 
<code>r</code>=8, <code>p</code>=1 (as of 2/1/2016 on commodity hardware) and 
should be increased to the threshold at which legitimate systems will encounter 
detrimental delays (see schedule below or use 
<code>ScryptCipherProviderGroovyTest#testDefaultConstructorShouldProvideStrongParameters()</code>
 to calculate safe minimums).</p>
+</li>
+<li>
+<p>The salt format is <code>$s0$e0101$ABCDEFGHIJKLMNOPQRSTUV</code>. The salt 
is delimited by <code>$</code> and the three sections are as follows:</p>
+<div class="ulist">
+<ul>
+<li>
+<p><code>s0</code> - the version of the format. NiFi currently uses 
<code>s0</code> for all salts generated internally.</p>
+</li>
+<li>
+<p><code>e0101</code> - the cost parameters. This is actually a hexadecimal 
encoding of <code>N</code>, <code>r</code>, <code>p</code> using shifts. This 
can be formed/parsed using <code>Scrypt#encodeParams()</code> and 
<code>Scrypt#parseParameters()</code>.</p>
+<div class="ulist">
+<ul>
+<li>
+<p>Some external libraries encode <code>N</code>, <code>r</code>, and 
<code>p</code> separately in the form <code>$400$1$1$</code>. A utility method 
is available at <code>ScryptCipherProvider#translateSalt()</code> which will 
convert the external form to the internal form.</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p><code>ABCDEFGHIJKLMNOPQRSTUV</code> - the 12-44 character, Base64-encoded, 
unpadded, raw salt value. This decodes to a 8-32 byte salt used in the key 
derivation.</p>
+</li>
+</ul>
+</div>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>PBKDF2</p>
+<div class="ulist">
+<ul>
+<li>
+<p>This KDF was added in v0.5.0.</p>
+</li>
+<li>
+<p><a href="https://en.wikipedia.org/wiki/PBKDF2";>Password-Based Key 
Derivation Function 2</a> is an adaptive derivation function which uses an 
internal pseudorandom function (PRF) and iterates it many times over a password 
and salt (at least 16 bytes).</p>
+</li>
+<li>
+<p>The PRF is recommended to be <code>HMAC/SHA-256</code> or 
<code>HMAC/SHA-512</code>. The use of an HMAC cryptographic hash function 
mitigates a length extension attack.</p>
+</li>
+<li>
+<p>The recommended minimum number of iterations is 160,000 (as of 2/1/2016 on 
commodity hardware). This number should be doubled every two years (see 
schedule below or use 
<code>PBKDF2CipherProviderGroovyTest#testDefaultConstructorShouldProvideStrongIterationCount()</code>
 to calculate safe minimums).</p>
+</li>
+<li>
+<p>This KDF is not memory-hard (can be parallelized massively with commodity 
hardware) but is still recommended as sufficient by <a 
href="http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf";>NIST
 SP 800-132 (PDF)</a> and many cryptographers (when used with a proper 
iteration count and HMAC cryptographic hash function).</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>None</p>
+<div class="ulist">
+<ul>
+<li>
+<p>This KDF was added in v0.5.0.</p>
+</li>
+<li>
+<p>This KDF performs no operation on the input and is a marker to indicate the 
raw key is provided to the cipher. The key must be provided in hexadecimal 
encoding and be of a valid length for the associated cipher/algorithm.</p>
+</li>
+</ul>
+</div>
+</li>
+</ul>
+</div>
+<div class="sect3">
+<h4 id="additional-resources"><a class="anchor" 
href="#additional-resources"></a>Additional Resources</h4>
+<div class="ulist">
+<ul>
+<li>
+<p><a href="http://stackoverflow.com/a/30308723/70465";>Explanation of optimal 
scrypt cost parameters and relationships</a></p>
+</li>
+<li>
+<p><a 
href="http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf";>NIST
 Special Publication 800-132</a></p>
+</li>
+<li>
+<p><a 
href="https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet#Work_Factor";>OWASP
 Password Storage Work Factor Calculations</a></p>
+</li>
+<li>
+<p><a href="http://security.stackexchange.com/a/3993/16485";>PBKDF2 rounds 
calculations</a></p>
+</li>
+<li>
+<p><a 
href="http://blog.ircmaxell.com/2014/03/why-i-dont-recommend-scrypt.html";>Scrypt
 as KDF vs password storage vulnerabilities</a></p>
+</li>
+<li>
+<p><a href="http://security.stackexchange.com/a/26253/16485";>Scrypt vs. Bcrypt 
(as of 2010)</a></p>
+</li>
+<li>
+<p><a href="http://security.stackexchange.com/a/6415/16485";>Bcrypt vs 
PBKDF2</a></p>
+</li>
+<li>
+<p><a 
href="http://wildlyinaccurate.com/bcrypt-choosing-a-work-factor/";>Choosing a 
work factor for Bcrypt</a></p>
+</li>
+<li>
+<p><a 
href="https://docs.spring.io/spring-security/site/docs/current/apidocs/org/springframework/security/crypto/bcrypt/BCrypt.html";>Spring
 Security Bcrypt</a></p>
+</li>
+<li>
+<p><a 
href="https://www.openssl.org/docs/manmaster/crypto/EVP_BytesToKey.html";>OpenSSL
 EVP BytesToKey PKCS#1v1.5</a></p>
+</li>
+<li>
+<p><a 
href="https://www.openssl.org/docs/manmaster/crypto/PKCS5_PBKDF2_HMAC.html";>OpenSSL
 PBKDF2 KDF</a></p>
+</li>
+<li>
+<p><a href="http://security.stackexchange.com/a/29139/16485";>OpenSSL KDF flaws 
description</a></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="salt-and-iv-encoding"><a class="anchor" 
href="#salt-and-iv-encoding"></a>Salt and IV Encoding</h3>
+<div class="paragraph">
+<p>Initially, the <code>EncryptContent</code> processor had a single method of 
deriving the encryption key from a user-provided password. This is now referred 
to as <code>NiFiLegacy</code> mode, effectively <code>MD5 digest, 1000 
iterations</code>. In v0.4.0, another method of deriving the key, <code>OpenSSL 
PKCS#5 v1.5 EVP_BytesToKey</code> was added for compatibility with content 
encrypted outside of NiFi using the <code>openssl</code> command-line tool. 
Both of these <a href="#key-derivation-functions">Key Derivation Functions</a> 
(KDF) had hard-coded digest functions and iteration counts, and the salt format 
was also hard-coded. With v0.5.0, additional KDFs are introduced with variable 
iteration counts, work factors, and salt formats. In addition, <em>raw keyed 
encryption</em> was also introduced. This required the capacity to encode 
arbitrary salts and Initialization Vectors (IV) into the cipher stream in order 
to be recovered by NiFi or a follow-on system to decrypt these mess
 ages.</p>
+</div>
+<div class="paragraph">
+<p>For the existing KDFs, the salt format has not changed.</p>
+</div>
+<div class="sect3">
+<h4 id="nifi-legacy"><a class="anchor" href="#nifi-legacy"></a>NiFi Legacy</h4>
+<div class="paragraph">
+<p>The first 8 or 16 bytes of the input are the salt. The salt length is 
determined based on the selected algorithm&#8217;s cipher block length. If the 
cipher block size cannot be determined (such as with a stream cipher like 
<code>RC4</code>), the default value of 8 bytes is used. On decryption, the 
salt is read in and combined with the password to derive the encryption key and 
IV.</p>
+</div>
+<div class="paragraph">
+<p><span class="image"><img src="./images/nifi-legacy-salt.png" alt="NiFi 
Legacy Salt Encoding"></span></p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="openssl-pkcs-5-v1-5-evp_bytestokey"><a class="anchor" 
href="#openssl-pkcs-5-v1-5-evp_bytestokey"></a>OpenSSL PKCS#5 v1.5 
EVP_BytesToKey</h4>
+<div class="paragraph">
+<p>OpenSSL allows for salted or unsalted key derivation. <em>*Unsalted key 
derivation is a security risk and is not recommended.*</em> If a salt is 
present, the first 8 bytes of the input are the ASCII string 
"<code>Salted__</code>" (<code>0x53 61 6C 74 65 64 5F 5F</code>) and the next 8 
bytes are the ASCII-encoded salt. On decryption, the salt is read in and 
combined with the password to derive the encryption key and IV. If there is no 
salt header, the entire input is considered to be the cipher text.</p>
+</div>
+<div class="paragraph">
+<p><span class="image"><img src="./images/openssl-salt.png" alt="OpenSSL Salt 
Encoding"></span></p>
+</div>
+<div class="paragraph">
+<p>For new KDFs, each of which allow for non-deterministic IVs, the IV must be 
stored alongside the cipher text. This is not a vulnerability, as the IV is not 
required to be secret, but simply to be unique for messages encrypted using the 
same key to reduce the success of cryptographic attacks. For these KDFs, the 
output consists of the salt, followed by the salt delimiter, UTF-8 string 
"<code>NiFiSALT</code>" (<code>0x4E 69 46 69 53 41 4C 54</code>) and then the 
IV, followed by the IV delimiter, UTF-8 string "<code>NiFiIV</code>" 
(<code>0x4E 69 46 69 49 56</code>), followed by the cipher text.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="bcrypt-scrypt-pbkdf2"><a class="anchor" 
href="#bcrypt-scrypt-pbkdf2"></a>Bcrypt, Scrypt, PBKDF2</h4>
+<div class="paragraph">
+<p><span class="image"><img src="./images/bcrypt-salt.png" alt="Bcrypt Salt 
&amp; IV Encoding"></span></p>
+</div>
+<div class="paragraph">
+<p><span class="image"><img src="./images/scrypt-salt.png" alt="Scrypt Salt 
&amp; IV Encoding"></span></p>
+</div>
+<div class="paragraph">
+<p><span class="image"><img src="./images/pbkdf2-salt.png" alt="PBKDF2 Salt 
&amp; IV Encoding"></span></p>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 
id="java-cryptography-extension-jce-limited-strength-jurisdiction-policies"><a 
class="anchor" 
href="#java-cryptography-extension-jce-limited-strength-jurisdiction-policies"></a>Java
 Cryptography Extension (JCE) Limited Strength Jurisdiction Policies</h3>
+<div class="paragraph">
+<p>Because of US export regulations, default JVMs have <a 
href="http://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html#importlimits";>limits
 imposed on the strength of cryptographic operations</a> available to them. For 
example, AES operations are limited to <code>128 bit keys</code> by default. 
While <code>AES-128</code> is cryptographically safe, this can have unintended 
consequences, specifically on Password-based Encryption (PBE).</p>
+</div>
+<div class="paragraph">
+<p>PBE is the process of deriving a cryptographic key for encryption or 
decryption from <em>user-provided secret material</em>, usually a password. 
Rather than a human remembering a (random-appearing) 32 or 64 character 
hexadecimal string, a password or passphrase is used.</p>
+</div>
+<div class="paragraph">
+<p>A number of PBE algorithms provided by NiFi impose strict limits on the 
length of the password due to the underlying key length checks. Below is a 
table listing the maximum password length on a JVM with limited cryptographic 
strength.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<caption class="title">Table 1. Maximum Password Length on Limited 
Cryptographic Strength JVM</caption>
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top">Algorithm</th>
+<th class="tableblock halign-left valign-top">Max Password Length</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><code>PBEWITHMD5AND128BITAES-CBC-OPENSSL</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><code>PBEWITHMD5AND192BITAES-CBC-OPENSSL</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><code>PBEWITHMD5AND256BITAES-CBC-OPENSSL</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><code>PBEWITHMD5ANDDES</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><code>PBEWITHMD5ANDRC2</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><code>PBEWITHSHA1ANDRC2</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><code>PBEWITHSHA1ANDDES</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><code>PBEWITHSHAAND128BITAES-CBC-BC</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">7</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><code>PBEWITHSHAAND192BITAES-CBC-BC</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">7</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><code>PBEWITHSHAAND256BITAES-CBC-BC</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">7</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><code>PBEWITHSHAAND40BITRC2-CBC</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">7</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><code>PBEWITHSHAAND128BITRC2-CBC</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">7</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><code>PBEWITHSHAAND40BITRC4</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">7</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><code>PBEWITHSHAAND128BITRC4</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">7</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><code>PBEWITHSHA256AND128BITAES-CBC-BC</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">7</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><code>PBEWITHSHA256AND192BITAES-CBC-BC</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">7</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><code>PBEWITHSHA256AND256BITAES-CBC-BC</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">7</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><code>PBEWITHSHAAND2-KEYTRIPLEDES-CBC</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">7</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><code>PBEWITHSHAAND3-KEYTRIPLEDES-CBC</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">7</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><code>PBEWITHSHAANDTWOFISH-CBC</code></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">7</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="allow-insecure-cryptographic-modes"><a class="anchor" 
href="#allow-insecure-cryptographic-modes"></a>Allow Insecure Cryptographic 
Modes</h3>
+<div class="paragraph">
+<p>By default, the <code>Allow Insecure Cryptographic Modes</code> property in 
<code>EncryptContent</code> processor settings is set to 
<code>not-allowed</code>. This means that if a password of fewer than 
<code>10</code> characters is provided, a validation error will occur. 10 
characters is a conservative estimate and does not take into consideration full 
entropy calculations, patterns, etc.</p>
+</div>
+<div class="paragraph">
+<p><span class="image"><img src="./images/allow-weak-crypto.png" alt="Allow 
Insecure Cryptographic Modes" width="940"></span></p>
+</div>
+<div class="paragraph">
+<p>On a JVM with limited strength cryptography, some PBE algorithms limit the 
maximum password length to 7, and in this case it will not be possible to 
provide a "safe" password. It is recommended to install the JCE Unlimited 
Strength Jurisdiction Policy files for the JVM to mitigate this issue.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><a 
href="http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html";>JCE
 Unlimited Strength Jurisdiction Policy files for Java 7</a></p>
+</li>
+<li>
+<p><a 
href="http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html";>JCE
 Unlimited Strength Jurisdiction Policy files for Java 8</a></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If on a system where the unlimited strength policies cannot be installed, 
it is recommended to switch to an algorithm that supports longer passwords (see 
table above).</p>
+</div>
+<div class="admonitionblock warning">
+<table>
+<tr>
+<td class="icon">
+<i class="fa icon-warning" title="Warning"></i>
+</td>
+<td class="content">
+<div class="title">Allowing Weak Crypto</div>
+<div class="paragraph">
+<p>If it is not possible to install the unlimited strength jurisdiction 
policies, the <code>Allow Weak Crypto</code> setting can be changed to 
<code>allowed</code>, but <strong>this is <em>not</em> recommended</strong>. 
Changing this setting explicitly acknowledges the inherent risk in using weak 
cryptographic configurations.</p>
+</div>
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>It is preferable to request upstream/downstream systems to switch to <a 
href="https://cwiki.apache.org/confluence/display/NIFI/Encryption+Information";>keyed
 encryption</a> or use a "strong" <a 
href="https://cwiki.apache.org/confluence/display/NIFI/Key+Derivation+Function+Explanations";>Key
 Derivation Function (KDF) supported by NiFi</a>.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
 <h2 id="clustering"><a class="anchor" href="#clustering"></a>Clustering 
Configuration</h2>
 <div class="sectionbody">
 <div class="paragraph">
@@ -1284,6 +1699,9 @@ the NiFi Cluster Manager (NCM), and the
 <p>Under the Web Properties, set either the http or https port that you want 
Node 1 to run on. If the NCM is running on the same server, choose a different 
web port for Node 1. Also, consider whether you need to set the http or https 
host property.</p>
 </li>
 <li>
+<p>Under the State Management section, set the 
<code>nifi.state.management.provider.cluster</code> property to the identifier 
of the Cluster State Provider. Ensure that the Cluster State Provider has been 
configured in the <em>state-management.xml</em> file. See <a 
href="#state_providers">Configuring State Providers</a> for more 
information.</p>
+</li>
+<li>
 <p>Under Cluster Node Properties, set the following:</p>
 <div class="ulist">
 <ul>
@@ -1316,6 +1734,9 @@ the NiFi Cluster Manager (NCM), and the
 <p>Under the Web Properties, set either the http or https port that you want 
Node 2 to run on. Also, consider whether you need to set the http or https host 
property.</p>
 </li>
 <li>
+<p>Under the State Management section, set the 
<code>nifi.state.management.provider.cluster</code> property to the identifier 
of the Cluster State Provider. Ensure that the Cluster State Provider has been 
configured in the <em>state-management.xml</em> file. See <a 
href="#state_providers">Configuring State Providers</a> for more 
information.</p>
+</li>
+<li>
 <p>Under the Cluster Node Properties, set the following:</p>
 <div class="ulist">
 <ul>
@@ -1362,6 +1783,391 @@ additivity="false"&gt;
 </div>
 </div>
 <div class="sect1">
+<h2 id="state_management"><a class="anchor" href="#state_management"></a>State 
Management</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>NiFi provides a mechanism for Processors, Reporting Tasks, Controller 
Services, and the framework itself to persist state. This
+allows a Processor, for example, to resume from the place where it left off 
after NiFi is restarted. Additionally, it allows for
+a Processor to store some piece of information so that the Processor can 
access that information from all of the different nodes
+in the cluster. This allows one node to pick up where another node left off, 
or to coordinate across all of the nodes in a cluster.</p>
+</div>
+<div class="sect2">
+<h3 id="state_providers"><a class="anchor" 
href="#state_providers"></a>Configuring State Providers</h3>
+<div class="paragraph">
+<p>When a component decides to store or retrieve state, it does so by 
providing a "Scope" - either Node-local or Cluster-wide. The
+mechanism that is used to store and retrieve this state is then determined 
based on this Scope, as well as the configured State
+Providers. The <em>nifi.properties</em> file contains three different 
properties that are relevant to configuring these State Providers.
+The first is the <code>nifi.state.management.configuration.file</code> 
property specifies an external XML file that is used for configuring
+the local and cluster-wide State Providers. This XML file may contain 
configurations for multiple providers, so the
+<code>nifi.state.management.provider.local</code> property provides the 
identifier of the local State Provider configured in this XML file.
+Similarly, the <code>nifi.state.management.provider.cluster</code> property 
provides the identifier of the cluster-wide State Provider
+configured in this XML file.</p>
+</div>
+<div class="paragraph">
+<p>This XML file consists of a top-level <code>state-management</code> 
element, which has one or more <code>local-provider</code> and zero or more
+<code>cluster-provider</code> elements. Each of these elements then contains 
an <code>id</code> element that is used to specify the identifier that can
+be referenced in the <em>nifi.properties</em> file, as well as a 
<code>class</code> element that specifies the fully-qualified class name to use
+in order to instantiate the State Provider. Finally, each of these elements 
may have zero or more <code>property</code> elements. Each
+<code>property</code> element has an attribute, <code>name</code> that is the 
name of the property that the State Provider supports. The textual content
+of the <code>property</code> element is the value of the property.</p>
+</div>
+<div class="paragraph">
+<p>Once these State Providers have been configured in the 
<em>state-management.xml</em> file (or whatever file is configured), those 
Providers
+may be referenced by their identifiers. By default, the Local State Provider 
is configured to be a <code>WriteAheadLocalStateProvider</code> that
+persists the data to the <em>$NIFI_HOME/state</em> directory. The default 
Cluster State Provider is configured to be a 
<code>ZooKeeperStateProvider</code>.
+The default ZooKeeper-based provider must have its <code>Connect String</code> 
property populated before it can be used. It is also advisable,
+if multiple NiFi instances will use the same ZooKeeper instance, that the 
value of the <code>Root Node</code> property be changed. For instance,
+one might set the value to <code>/nifi/&lt;team name&gt;/production</code>. A 
<code>Connect String</code> takes the form of comma separated 
&lt;host&gt;:&lt;port&gt; tuples,
+such as my-zk-server1:2181,my-zk-server2:2181,my-zk-server3:2181. In the event 
a port is not specified for any of the hosts, the ZooKeeper
+default of 2181 is assumed.</p>
+</div>
+<div class="paragraph">
+<p>When adding data to ZooKeeper, there are two options for Access Control: 
<code>Open</code> and <code>CreatorOnly</code>. If the <code>Access 
Control</code> property is
+set to <code>Open</code>, then anyone is allowed to log into ZooKeeper and 
have full permissions to see, change, delete, or administer the data.
+If <code>CreatorOnly</code> is specified, then only the user that created the 
data is allowed to read, change, delete, or administer the data.
+In order to use the <code>CreatorOnly</code> option, NiFi must provide some 
form of authentication. See the <a href="#zk_access_control">ZooKeeper Access 
Control</a>
+section below for more information on how to configure authentication.</p>
+</div>
+<div class="paragraph">
+<p>If NiFi is configured to run in a standalone mode, the 
<code>cluster-provider</code> element need not be populated in the 
<em>state-management.xml</em>
+file and will actually be ignored if they are populated. However, the 
<code>local-provider</code> element must always be present and populated.
+Additionally, if NiFi is run in a cluster, each node must also have the 
<code>cluster-provider</code> element present and properly configured.
+Otherwise, NiFi will fail to startup.</p>
+</div>
+<div class="paragraph">
+<p>While there are not many properties that need to be configured for these 
providers, they were externalized into a separate <em>state-management.xml</em>
+file, rather than being configured via the <em>nifi.properties</em> file, 
simply because different implementations may require different properties,
+and it is easier to maintain and understand the configuration in an XML-based 
file such as this, than to mix the properties of the Provider
+in with all of the other NiFi framework-specific properties.</p>
+</div>
+<div class="paragraph">
+<p>It should be noted that if Processors and other components save state using 
the Clustered scope, the Local State Provider will be used
+if the instance is a standalone instance (not in a cluster) or is disconnected 
from the cluster. This also means that if a standalone instance
+is migrated to become a cluster, then that state will no longer be available, 
as the component will begin using the Clustered State Provider
+instead of the Local State Provider.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="embedded_zookeeper"><a class="anchor" 
href="#embedded_zookeeper"></a>Embedded ZooKeeper Server</h3>
+<div class="paragraph">
+<p>As mentioned above, the default State Provider for cluster-wide state is 
the <code>ZooKeeperStateProvider</code>. At the time of this writing, this is 
the
+only State Provider that exists for handling cluster-wide state. What this 
means is that NiFi has dependencies on ZooKeeper in order to
+behave as a cluster. However, there are many environments in which NiFi is 
deployed where there is no existing ZooKeeper ensemble being maintained.
+In order to avoid the burden of forcing administrators to also maintain a 
separate ZooKeeper instance, NiFi provides the option of starting an
+embedded ZooKeeper server.</p>
+</div>
+<div class="paragraph">
+<p>This can be accomplished by setting the 
<code>nifi.state.management.embedded.zookeeper.start</code> property in 
<em>nifi.properties</em> to <code>true</code> on those nodes
+that should run the embedded ZooKeeper server. Generally, it is advisable to 
run ZooKeeper on either 3 or 5 nodes. Running on fewer than 3 nodes
+provides less durability in the face of failure. Running on more than 5 nodes 
generally produces more network traffic than is necessary. Additionally,
+running ZooKeeper on 4 nodes provides no more benefit than running on 3 nodes, 
ZooKeeper requires a majority of nodes be active in order to function.
+However, it is up to the administrator to determine the number of nodes most 
appropriate to the particular deployment of NiFi.</p>
+</div>
+<div class="paragraph">
+<p>If the <code>nifi.state.management.embedded.zookeeper.start</code> property 
is set to <code>true</code>, the 
<code>nifi.state.management.embedded.zookeeper.properties</code> property
+in <em>nifi.properties</em> also becomes relevant. This specifies the 
ZooKeeper properties file to use. At a minimum, this properties file needs to 
be populated
+with the list of ZooKeeper servers. The servers are specified as properties in 
the form of <code>server.1</code>, <code>server.2</code>, to 
<code>server.n</code>. Each of these servers is
+configured as &lt;hostname&gt;:&lt;quorum port&gt;[:&lt;leader election 
port&gt;]. For example, <code>myhost:2888:3888</code>. This list of nodes 
should be the same nodes in the NiFi
+cluster that have the 
<code>nifi.state.management.embedded.zookeeper.start</code> property set to 
<code>true</code>. Also note that because ZooKeeper will be listening on these
+ports, the firewall may need to be configured to open these ports for incoming 
traffic, at least between nodes in the cluster. Additionally, the port to
+listen on for client connections must be opened in the firewall. The default 
value for this is <em>2181</em> but can be configured via the 
<em>clientPort</em> property
+in the <em>zookeeper.properties</em> file.</p>
+</div>
+<div class="paragraph">
+<p>When using an embedded ZooKeeper, the <em>conf/zookeeper.properties</em> 
file has a property named <code>dataDir</code>. By default, this value is set 
to <code>./state/zookeeper</code>.
+If more than one NiFi node is running an embedded ZooKeeper, it is important 
to tell the server which one it is. This is accomplished by creating a file 
named
+<em>myid</em> and placing it in ZooKeeper&#8217;s data directory. The contents 
of this file should be the index of the server as specific by the 
<code>server.&lt;number&gt;</code>. So for
+one of the ZooKeeper servers, we will accomplish this by performing the 
following commands:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>cd $NIFI_HOME
+mkdir state
+mkdir state/zookeeper
+echo 1 &gt; state/zookeeper/myid</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>For the next NiFi Node that will run ZooKeeper, we can accomplish this by 
performing the following commands:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>cd $NIFI_HOME
+mkdir state
+mkdir state/zookeeper
+echo 2 &gt; state/zookeeper/myid</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>And so on.</p>
+</div>
+<div class="paragraph">
+<p>For more information on the properties used to administer ZooKeeper, see the
+<a 
href="https://zookeeper.apache.org/doc/current/zookeeperAdmin.html";>ZooKeeper 
Admin Guide</a>.</p>
+</div>
+<div class="paragraph">
+<p>For information on securing the embedded ZooKeeper Server, see the <a 
href="#securing_zookeeper">Securing ZooKeeper</a> section below.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="zk_access_control"><a class="anchor" 
href="#zk_access_control"></a>ZooKeeper Access Control</h3>
+<div class="paragraph">
+<p>ZooKeeper provides Access Control to its data via an Access Control List 
(ACL) mechanism. When data is written to ZooKeeper, NiFi will provide an ACL
+that indicates that any user is allowed to have full permissions to the data, 
or an ACL that indicates that only the user that created the data is
+allowed to access the data. Which ACL is used depends on the value of the 
<code>Access Control</code> property for the 
<code>ZooKeeperStateProvider</code> (see the
+<a href="#state_providers">Configuring State Providers</a> section for more 
information).</p>
+</div>
+<div class="paragraph">
+<p>In order to use an ACL that indicates that only the Creator is allowed to 
access the data, we need to tell ZooKeeper who the Creator is. There are two
+mechanisms for accomplishing this. The first mechanism is to provide 
authentication using Kerberos. See <a href="#zk_kerberos_client">Kerberizing 
NiFi&#8217;s ZooKeeper Client</a> for more information.</p>
+</div>
+<div class="paragraph">
+<p>The second option is to use a user name and password. This is configured by 
specifying a value for the <code>Username</code> and a value for the 
<code>Password</code> properties
+for the <code>ZooKeeperStateProvider</code> (see the <a 
href="#state_providers">Configuring State Providers</a> section for more 
information). The important thing to keep in mind here, though, is that 
ZooKeeper
+will pass around the password in plain text. This means that using a user name 
and password should not be used unless ZooKeeper is running on localhost as a
+one-instance cluster, or if communications with ZooKeeper occur only over 
encrypted communications, such as a VPN or an SSL connection. ZooKeeper will be
+providing support for SSL connections in version 3.5.0.</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="securing_zookeeper"><a class="anchor" 
href="#securing_zookeeper"></a>Securing ZooKeeper</h3>
+<div class="paragraph">
+<p>When NiFi communicates with ZooKeeper, all communications, by default, are 
non-secure, and anyone who logs into ZooKeeper is able to view and manipulate 
all
+of the NiFi state that is stored in ZooKeeper. To prevent this, we can use 
Kerberos to manage the authentication. At this time, ZooKeeper does not provide
+support for encryption via SSL. Support for SSL in ZooKeeper is being actively 
developed and is expected to be available in the 3.5.x release version.</p>
+</div>
+<div class="paragraph">
+<p>In order to secure the communications, we need to ensure that both the 
client and the server support the same configuration. Instructions for 
configuring the
+NiFi ZooKeeper client and embedded ZooKeeper server to use Kerberos are 
provided below.</p>
+</div>
+<div class="sect3">
+<h4 id="zk_kerberos_client"><a class="anchor" 
href="#zk_kerberos_client"></a>Kerberizing NiFi&#8217;s ZooKeeper Client</h4>
+<div class="paragraph">
+<p>The preferred mechanism for authenticating users with ZooKeeper is to use 
Kerberos. In order to use Kerberos to authenticate, we must configure a few
+system properties, so that the ZooKeeper client knows who the user is and 
where the KeyTab file is. All nodes configured to store cluster-wide state
+using <code>ZooKeeperStateProvider</code> and using Kerberos should follow 
these steps.</p>
+</div>
+<div class="paragraph">
+<p>First, we must create the Principal that we will use when communicating 
with ZooKeeper. This is generally done via the <code>kadmin</code> tool:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>kadmin: addprinc "[email protected]"</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>A Kerberos Principal is made up of three parts: the primary, the instance, 
and the realm. Here, we are creating a Principal with the primary 
<code>nifi</code>,
+no instance, and the realm <code>EXAMPLE.COM</code>. The primary 
(<code>nifi</code>, in this case) is the identifier that will be used to 
identify the user when authenticating
+via Kerberos.</p>
+</div>
+<div class="paragraph">
+<p>After we have created our Principal, we will need to create a KeyTab for 
the Principal:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>kadmin: xst -k nifi.keytab 
[email protected]</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This will create a file in the current directory named 
<code>nifi.keytab</code>. We can now copy that file into the 
<em>$NIFI_HOME/conf/</em> directory. We should ensure
+that only the user that will be running NiFi is allowed to read this file.</p>
+</div>
+<div class="paragraph">
+<p>Next, we need to configure NiFi to use this KeyTab for authentication. 
Since ZooKeeper uses the Java Authentication and Authorization Service (JAAS), 
we need to
+create a JAAS-compatible file. In the <code>$NIFI_HOME/conf/</code> directory, 
create a file named <code>zookeeper-jaas.conf</code> and add to it the 
following snippet:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>Client {
+  com.sun.security.auth.module.Krb5LoginModule required
+  useKeyTab=true
+  keyTab="./conf/nifi.keytab"
+  storeKey=true
+  useTicketCache=false
+  principal="[email protected]";
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Finally, we need to tell NiFi to use this as our JAAS configuration. This 
is done by setting a JVM System Property, so we will edit the 
<em>conf/bootstrap.conf</em> file.
+We add the following line anywhere in this file in order to tell the NiFi JVM 
to use this configuration:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre 
class="highlight"><code>java.arg.15=-Djava.security.auth.login.config=./conf/zookeeper-jaas.conf</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>We can initialize our Kerberos ticket by running the following command:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>kinit nifi</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Note, the above <code>kinit</code> command requires that Kerberos client 
libraries be installed. This is accomplished in Fedora-based Linux 
distributions via:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>yum install krb5-workstation krb5-libs 
krb5-auth-dialog</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Once this is complete, the /etc/krb5.conf will need to be configured 
appropriately for your organization&#8217;s Kerberos envrionment.</p>
+</div>
+<div class="paragraph">
+<p>Now, when we start NiFi, it will use Kerberos to authentication as the 
<code>nifi</code> user when communicating with ZooKeeper.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="zk_kerberos_server"><a class="anchor" 
href="#zk_kerberos_server"></a>Kerberizing Embedded ZooKeeper Server</h4>
+<div class="paragraph">
+<p>When using the embedded ZooKeeper server, we may choose to secure the 
server by using Kerberos. All nodes configured to launch an embedded ZooKeeper
+and using Kerberos should follow these steps.</p>
+</div>
+<div class="paragraph">
+<p>If Kerberos is not already setup in your environment, you can find 
information on installing and setting up a Kerberos Server at
+<a 
href="https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Managing_Smart_Cards/Configuring_a_Kerberos_5_Server.html";>https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Managing_Smart_Cards/Configuring_a_Kerberos_5_Server.html</a>
+. This guide assumes that Kerberos already has been installed in the 
environment in which NiFi is running.</p>
+</div>
+<div class="paragraph">
+<p>In order to use Kerberos, we first need to generate a Kerberos Principal 
for our ZooKeeper server. This is accomplished via the <code>kadmin</code> 
tool:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>kadmin: addprinc 
"zookeeper/[email protected]"</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Here, we are creating a Principal with the primary 
<code>zookeeper/myHost.example.com</code>, using the realm 
<code>EXAMPLE.COM</code>. We need to use a Principal whose
+name is <code>&lt;service name&gt;/&lt;instance name&gt;</code>. In this case, 
the service is <code>zookeeper</code> and the instance name is 
<code>myHost.example.com</code> (the fully qualified name of our host).</p>
+</div>
+<div class="paragraph">
+<p>Next, we will need to create a KeyTab for this Principal:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>kadmin: xst -k zookeeper-server.keytab 
zookeeper/[email protected]</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This will create a file in the current directory named 
<code>zookeeper-server.keytab</code>. We can now copy that file into the 
<code>$NIFI_HOME/conf/</code> directory. We should ensure
+that only the user that will be running NiFi is allowed to read this file.</p>
+</div>
+<div class="paragraph">
+<p>We will need to repeat the above steps for each of the instances of NiFi 
that will be running the embedded ZooKeeper server, being sure to replace 
<em>myHost.example.com</em> with
+<em>myHost2.example.com</em>, or whatever fully qualified hostname the 
ZooKeeper server will be run on.</p>
+</div>
+<div class="paragraph">
+<p>Now that we have our KeyTab for each of the servers that will be running 
NiFi, we will need to configure NiFi&#8217;s embedded ZooKeeper server to use 
this configuration.
+ZooKeeper uses the Java Authentication and Authorization Service (JAAS), so we 
need to create a JAAS-compatible file In the <code>$NIFI_HOME/conf/</code> 
directory, create a file
+named <code>zookeeper-jaas.conf</code> (this file will already exist if the 
Client has already been configured to authenticate via Kerberos. That&#8217;s 
okay, just add to the file).
+We will add to this file, the following snippet:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>Server {
+  com.sun.security.auth.module.Krb5LoginModule required
+  useKeyTab=true
+  keyTab="./conf/zookeeper-server.keytab"
+  storeKey=true
+  useTicketCache=false
+  principal="zookeeper/[email protected]";
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Be sure to replace the value of <em>principal</em> above with the 
appropriate Principal, including the fully qualified domain name of the 
server.</p>
+</div>
+<div class="paragraph">
+<p>Next, we need to tell NiFi to use this as our JAAS configuration. This is 
done by setting a JVM System Property, so we will edit the 
<code>conf/bootstrap.conf</code> file.
+If the Client has already been configured to use Kerberos, this is not 
necessary, as it was done above. Otherwise, we will add the following line to 
our <em>bootstrap.conf</em> file:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre 
class="highlight"><code>java.arg.15=-Djava.security.auth.login.config=./conf/zookeeper-jaas.conf</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>We will want to initialize our Kerberos ticket by running the following 
command:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>kinit 
"zookeeper/[email protected]"</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Again, be sure to replace the Principal with the appropriate value, 
including your realm and your fully qualified hostname.</p>
+</div>
+<div class="paragraph">
+<p>Finally, we need to tell the Kerberos server to use the SASL Authentication 
Provider. To do this, we edit the 
<code>$NIFI_HOME/conf/zookeeper.properties</code> file and add the following
+lines:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre 
class="highlight"><code>authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
+jaasLoginRenew=3600000
+requireClientAuthScheme=sasl</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The last line is optional but specifies that clients MUST use Kerberos to 
communicate with our ZooKeeper instance.</p>
+</div>
+<div class="paragraph">
+<p>Now, we can start NiFi, and the embedded ZooKeeper server will use Kerberos 
as the authentication mechanism.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="troubleshooting_kerberos"><a class="anchor" 
href="#troubleshooting_kerberos"></a>Troubleshooting Kerberos Configuration</h4>
+<div class="paragraph">
+<p>When using Kerberos, it is import to use fully-qualified domain names and 
not use <em>localhost</em>. Please ensure that the fully qualified hostname of 
each server is used
+in the following locations:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><em>conf/zookeeper.properties</em> file should use FQDN for 
<code>server.1</code>, <code>server.2</code>, &#8230;&#8203;, 
<code>server.N</code> values.</p>
+</li>
+<li>
+<p>The <code>Connect String</code> property of the ZooKeeperStateProvider</p>
+</li>
+<li>
+<p>The /etc/hosts file should also resolve the FQDN to an IP address that is 
<strong>not</strong> <em>127.0.0.1</em>.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Failure to do so, may result in errors similar to the following:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>2016-01-08 16:08:57,888 ERROR 
[pool-26-thread-1-SendThread(localhost:2181)] 
o.a.zookeeper.client.ZooKeeperSaslClient An error: 
(java.security.PrivilegedActionException: javax.security.sasl.SaslException: 
GSS initiate failed [Caused by GSSException: No valid credentials provided 
(Mechanism level: Server not found in Kerberos database (7) - 
LOOKING_UP_SERVER)]) occurred when evaluating Zookeeper Quorum Member's  
received SASL token. Zookeeper Client will go to AUTH_FAILED state.</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>If there are problems communicating or authenticating with Kerberos,
+<a 
href="http://docs.oracle.com/javase/7/docs/technotes/guides/security/jgss/tutorials/Troubleshooting.html";>this
 Troubleshooting Guide</a> may be of value.</p>
+</div>
+<div class="paragraph">
+<p>One of the most important notes in the above Troubleshooting guide is the 
mechanism for turning on Debug output for Kerberos.
+This is done by setting the <code>sun.security.krb5.debug</code> environment 
variable.
+In NiFi, this is accomplished by adding the following line to the 
_$NIFI_HOME/conf/bootstrap.conf` file:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre 
class="highlight"><code>java.arg.16=-Dsun.security.krb5.debug=true</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This will cause the debug output to be written to the NiFi Bootstrap log 
file. By default, this is located at 
<em>$NIFI_HOME/logs/nifi-bootstrap.log</em>.
+This output can be rather verbose but provides extremely valuable information 
for troubleshooting Kerberos failures.</p>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
 <h2 id="bootstrap_properties"><a class="anchor" 
href="#bootstrap_properties"></a>Bootstrap Properties</h2>
 <div class="sectionbody">
 <div class="paragraph">
@@ -1441,6 +2247,34 @@ take effect only after NiFi has been sto
 </tr>
 </tbody>
 </table>
+<div class="paragraph">
+<p><strong>Java 7 PermGen Sizing</strong>
+The provided <em>bootstrap.conf</em> file may include a line such as</p>
+</div>
+<div class="literalblock">
+<div class="content">
+<pre>#java.arg.11=-XX:PermSize=128M
+#java.arg.12=-XX:MaxPermSize=128M</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>If running in Java 7 it is recommended to uncomment those lines to ensure 
the PermGen size and maximum can be larger than is available by default.  This 
is important because NiFi
+can load a significant number of classes which will result in OutOfMemoryError 
due to PermGen being full.  You might choose a value larger than 128MB as 
well.</p>
+</div>
+<div class="paragraph">
+<p><strong>Java 7 and 8 handling of codecache</strong>
+It has been observed in both Java 7 and Java 8 runtime environments that 
performance can suddenly drop by more than an order of magnitude after days or 
weeks of otherwise ideal
+behavior.  This has only been observed under extremely high load and in cases 
where considerable Just in Time (JIT) compilation occurs.  The core problem is 
the CodeCache becomes
+full and is seemingly not properly garbage collected or grown.  When this 
occurs JIT seems to no longer occur or involve considerable delays and 
performance drops.
+This is easily overcome by ensuring the following lines are available in the 
<em>boostrap.conf</em>.  By default they are there but commented.  Uncomment 
them for maximum sustained throughput.</p>
+</div>
+<div class="literalblock">
+<div class="content">
+<pre>#java.arg.7=-XX:ReservedCodeCacheSize=256m
+#java.arg.8=-XX:CodeCacheFlushingMinimumFreeSpace=10m
+#java.arg.9=-XX:+UseCodeCacheFlushing</pre>
+</div>
+</div>
 </div>
 </div>
 <div class="sect1">
@@ -1690,6 +2524,45 @@ only consider if <code>nifi.security.use
 </tbody>
 </table>
 <div class="paragraph">
+<p><strong>State Management</strong><br></p>
+</div>
+<div class="paragraph">
+<p>The State Management section of the Properties file provides a mechanism 
for configuring local and cluster-wide mechanisms
+for components to persist state. See the <a href="#state_management">State 
Management</a> section for more information on how this is used.</p>
+</div>
+<table class="tableblock frame-all grid-all spread">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><strong>Property</strong></p></td>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock"><strong>Description</strong></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock">nifi.state.management.configuration.file</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The XML 
file that contains configuration for the local and cluster-wide State 
Providers. The default value is <em>./conf/state-management.xml</em></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock">nifi.state.management.provider.local</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The ID of 
the Local State Provider to use. This value must match the value of the 
<code>id</code> element of one of the <code>local-provider</code> elements in 
the <em>state-management.xml</em> file.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock">nifi.state.management.provider.cluster</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The ID of 
the Cluster State Provider to use. This value must match the value of the 
<code>id</code> element of one of the <code>cluster-provider</code> elements in 
the <em>state-management.xml</em> file. This value is ignored if not clustered 
but is required for nodes in a cluster.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock">nifi.state.management.embedded.zookeeper.start</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies 
whether or not this instance of NiFi should start an embedded ZooKeeper Server. 
This is used in conjunction with the ZooKeeperStateProvider.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p 
class="tableblock">nifi.state.management.embedded.zookeeper.properties</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies 
a properties file that contains the configuration for the embedded ZooKeeper 
Server that is started (if the `</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
 <p><strong>H2 Settings</strong><br></p>
 </div>
 <div class="paragraph">
@@ -1999,6 +2872,13 @@ Providing three total locations, includi
 <p>The Component Status Repository contains the information for the Component 
Status History tool in the User Interface. These
 properties govern how that tool works.</p>
 </div>
+<div class="paragraph">
+<p>The buffer.size and snapshot.frequency work together to determine the 
amount of historical data to retain. As an example to
+configure two days worth of historical data with a data point snapshot 
occurring every 5 minutes you would configure
+snapshot.frequency to be "5 mins" and the buffer.size to be "576". To further 
explain this example for every 60 minutes there
+are 12 (60 / 5) snapshot windows for that time period. To keep that data for 
48 hours (12 * 48) you end up with a buffer size
+of 576.</p>
+</div>
 <table class="tableblock frame-all grid-all spread">
 <colgroup>
 <col style="width: 50%;">
@@ -2015,11 +2895,11 @@ properties govern how that tool works.</
 </tr>
 <tr>
 <td class="tableblock halign-left valign-top"><p 
class="tableblock">nifi.components.status.repository.buffer.size</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies 
the buffer size for the Component Status Repository. The default value is 
288.</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies 
the buffer size for the Component Status Repository. The default value is 
1440.</p></td>
 </tr>
 <tr>
 <td class="tableblock halign-left valign-top"><p 
class="tableblock">nifi.components.status.snapshot.frequency</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">This value 
indicates how often to present a snapshot of the components' status history. 
The default value is 5 mins.</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This value 
indicates how often to present a snapshot of the components' status history. 
The default value is 1 min.</p></td>
 </tr>
 </tbody>
 </table>
@@ -2118,11 +2998,11 @@ Security Configuration section of this A
 </tr>
 <tr>
 <td class="tableblock halign-left valign-top"><p 
class="tableblock">nifi.sensitive.props.key</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">This is 
the password used to encrypt any sensitive property values that are configured 
in processors. By default, it is blank, but the system administrator should 
provide a value for it. It can be a string of any length. Be aware that once 
this password is set and one or more sensitive processor properties have been 
configured, this password should not be changed.</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">This is 
the password used to encrypt any sensitive property values that are configured 
in processors. By default, it is blank, but the system administrator should 
provide a value for it. It can be a string of any length, although the 
recommended minimum length is 10 characters. Be aware that once this password 
is set and one or more sensitive processor properties have been configured, 
this password should not be changed.</p></td>
 </tr>
 <tr>
 <td class="tableblock halign-left valign-top"><p 
class="tableblock">nifi.sensitive.props.algorithm</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">The 
algorithm used to encrypt sensitive properties. The default value is 
PBEWITHMD5AND256BITAES-CBC-OPENSSL.</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The 
algorithm used to encrypt sensitive properties. The default value is 
<code>PBEWITHMD5AND256BITAES-CBC-OPENSSL</code>.</p></td>
 </tr>
 <tr>
 <td class="tableblock halign-left valign-top"><p 
class="tableblock">nifi.sensitive.props.provider</p></td>
@@ -2410,7 +3290,7 @@ If multicast is used, the following nifi
 </div>
 <div id="footer">
 <div id="footer-text">
-Last updated 2015-12-08 13:53:16 -05:00
+Last updated 2016-02-16 10:19:45 EST
 </div>
 </div>
 </body>

Modified: nifi/site/trunk/docs/nifi-docs/html/developer-guide.html
URL: 
http://svn.apache.org/viewvc/nifi/site/trunk/docs/nifi-docs/html/developer-guide.html?rev=1730775&r1=1730774&r2=1730775&view=diff
==============================================================================
--- nifi/site/trunk/docs/nifi-docs/html/developer-guide.html (original)
+++ nifi/site/trunk/docs/nifi-docs/html/developer-guide.html Wed Feb 17 
02:15:29 2016
@@ -462,6 +462,7 @@ body.book #toc,body.book #preamble,body.
 <li><a href="#supporting_api">Supporting API</a></li>
 <li><a href="#AbstractProcessor">AbstractProcessor API</a></li>
 <li><a href="#component-lifecycle">Component Lifecycle</a></li>
+<li><a href="#state_manager">State Manager</a></li>
 <li><a href="#reporting-processor-activity">Reporting Processor 
Activity</a></li>
 </ul>
 </li>
@@ -800,11 +801,13 @@ the <code>build</code> method.</p>
 <div class="sect3">
 <h4 id="validator"><a class="anchor" href="#validator"></a>Validator</h4>
 <div class="paragraph">
-<p>A PropertyDescriptor may specify one or more Validators that can be
+<p>A PropertyDescriptor MUST specify one or more Validators that can be
 used to ensure that the user-entered value
 for a property is valid. If a Validator indicates that a property
 value is invalid, the Component will not be
-able to be run or used until the property becomes valid.</p>
+able to be run or used until the property becomes valid. If a
+Validator is not specified, the Component will be assumed invalid and
+NiFi will report that the property is not supported.</p>
 </div>
 </div>
 <div class="sect3">
@@ -839,6 +842,16 @@ to fill in the details of the Relationsh
 </div>
 </div>
 <div class="sect3">
+<h4 id="supporting_api_state_manager"><a class="anchor" 
href="#supporting_api_state_manager"></a>StateManager</h4>
+<div class="paragraph">
+<p>The StateManager provides Processors, Reporting Tasks, and Controller 
Services a mechanism
+for easily storing and retrieving state. The API is similar to that of 
ConcurrentHashMap
+but requires a Scope for each operation. The Scope indicates whether the state 
is to be
+retrieved/stored locally or in a cluster-wide manner. For more information, 
see the
+<a href="#state_manager">State Manager</a> section.</p>
+</div>
+</div>
+<div class="sect3">
 <h4 id="processor_initialization_context"><a class="anchor" 
href="#processor_initialization_context"></a>ProcessorInitializationContext</h4>
 <div class="paragraph">
 <p>After a Processor is created, its <code>initialize</code> method will be 
called
@@ -1219,6 +1232,74 @@ relied upon for critical business logic.
 </div>
 </div>
 <div class="sect2">
+<h3 id="state_manager"><a class="anchor" href="#state_manager"></a>State 
Manager</h3>
+<div class="paragraph">
+<p>From the ProcessContext, ReportingContext, and 
ControllerServiceInitializationContext, components are
+able to call the <code>getStateManager()</code> method. This State Manager is 
responsible for providing a simple API
+for storing and retrieving state. As such, the API is designed to be quite 
similar to the ConcurrentMap
+API, which most Java developers are already familiar with.</p>
+</div>
+<div class="sect3">
+<h4 id="state_scope"><a class="anchor" href="#state_scope"></a>Scope</h4>
+<div class="paragraph">
+<p>One very notable difference between the StateManager API and the 
ConcurrentMap API, however, is the presence
+of a Scope object on each method call of the StateManager. This Scope will 
either be <code>Scope.NODE</code> or <code>Scope.CLUSTER</code>.
+If NiFi is run in a cluster, this Scope provides important information to the 
framework about how the operation should
+occur.</p>
+</div>
+<div class="paragraph">
+<p>If state as stored using <code>Scope.CLUSTER</code>, then all nodes in the 
cluster will be communicating with the same
+state storage mechanism, as if all nodes were to share a single ConcurrentMap. 
If state is stored and retrieved using
+<code>Scope.NODE</code>, then each node will see a different representation of 
the state.</p>
+</div>
+<div class="paragraph">
+<p>It is also worth noting that if NiFi is configured to run as a standalone 
instance, rather than running in a cluster,
+a scope of <code>Scope.NODE</code> is always used. This is done in order to 
allow the developer of a NiFi component to write the code
+in one consistent way, without worrying about whether or not the NiFi instance 
is clustered. The developer should instead assume
+that the instance is clustered and write the code accordingly.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="storing-and-retrieving-state"><a class="anchor" 
href="#storing-and-retrieving-state"></a>Storing and Retrieving State</h4>
+<div class="paragraph">
+<p>State is stored using the StateManager&#8217;s <code>set</code>, 
<code>replace</code>, <code>putIfAbsent</code>, <code>remove</code>, and 
<code>clear</code> methods. All of these methods,
+with the exception of <code>clear</code> take as the first argument the key to 
be set. The key that is used is unique only to the same
+instance of the component and for the same Scope. That is, if two Processors 
store a value using the key <em>My Key</em>, those Processors
+will not conflict with each other, even if both Processors are of the same 
type (e.g., both are of type ListFile) and scope. Furthermore,
+if a Processor stores a value with the key of <em>My Key</em> using the 
<code>Scope.CLUSTER</code> scope, and then attempts to retrieve the value
+using the <code>Scope.NODE</code> scope, the value retrieved will be 
<code>null</code>. Each Processor&#8217;s state, then, is stored in isolation 
from other
+Processors' state. A unique key can be thought of as a triple of &lt;Processor 
Instance, Key, Scope&gt;.</p>
+</div>
+<div class="paragraph">
+<p>It follows, then, that two Processors cannot share the same state. There 
are, however, some circumstances in which it is very
+necessary to share state between two Processors of different types, or two 
Processors of the same type. This can be accomplished
+by using a Controller Service. By storing and retrieving state from a 
Controller Service, multiple Processors can use the same
+Controller Service and the state can be exposed via the Controller 
Service&#8217;s API.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="unit-tests"><a class="anchor" href="#unit-tests"></a>Unit Tests</h4>
+<div class="paragraph">
+<p>NiFi&#8217;s Mock Framework provides an extensive collection of tools to 
perform unit testing of Processors. Processor unit tests typically
+begin with the <code>TestRunner</code> class. As a result, the 
<code>TestRunner</code> class contains a <code>getStateManager</code> method of 
its own. The StateManager
+that is returned, however, is of a specific type: 
<code>MockStateManager</code>. This implementation provides several methods in 
addition to those
+defined by the <code>StateManager</code> interface, that help developers to 
more easily develop unit tests.</p>
+</div>
+<div class="paragraph">
+<p>First, the <code>MockStateManager</code> implements the 
<code>StateManager</code> interface, so all of the state can be examined from 
within a unit test.
+Additionally, the <code>MockStateManager</code> exposes a handful of 
<code>assert*</code> methods to perform assertions that the State is set as 
expected.
+There are times, however, that state could be updated multiple times during 
the run of a single invocation of a Processor&#8217;s <code>onTrigger</code>
+method. In this case, inspecting the values after running the Processor may 
not be sufficient. Additionally, we must always remember at each
+step to check the value of the stored state, which can become error-prone and 
burdensome for the developer.</p>
+</div>
+<div class="paragraph">
+<p>For these reasons, the <code>MockStateManager</code> provides an additional 
method, named <code>failIfStateSet</code>. This method instructs the State 
Manager that
+the unit test should immediately fail if the state for a given key is ever 
set, or if it is set to a specific value. The <code>doNotFailIfStateSet</code>
+method can then be used to instruct the Mock Framework to clear this state and 
allow state to be set to any value.</p>
+</div>
+</div>
+</div>
+<div class="sect2">
 <h3 id="reporting-processor-activity"><a class="anchor" 
href="#reporting-processor-activity"></a>Reporting Processor Activity</h3>
 <div class="paragraph">
 <p>Processors are responsible for reporting their activity so that users
@@ -1396,7 +1477,7 @@ public final class InvokeHTTP extends Ab
 <div class="sect2">
 <h3 id="documenting-related-components"><a class="anchor" 
href="#documenting-related-components"></a>Documenting Related Components</h3>
 <div class="paragraph">
-<p>Often Processors and ControllerServices are related to one another.  
Sometimes its a put/get relation as in <code>PutFile</code> and 
<code>GetFile</code>.
+<p>Often Processors and ControllerServices are related to one another.  
Sometimes it is a put/get relation as in <code>PutFile</code> and 
<code>GetFile</code>.
 Sometimes a Processor uses a ControllerService like <code>InvokeHTTP</code> 
and <code>StandardSSLContextService</code>.  Sometimes one ControllerService 
uses another
 like <code>DistributedMapCacheClientService</code> and 
<code>DistributedMapCacheServer</code>.  Developers of these extension points 
may relate these
 different components using the <code>SeeAlso</code> tag.  This annotation 
links these components in the documentation.
@@ -2557,7 +2638,7 @@ that references a Controller Service as
 <div class="content">
 <pre class="highlight"><code class="language-java" data-lang="java">public 
static final PropertyDescriptor SSL_CONTEXT_SERVICE = new 
PropertyDescriptor.Builder()
   .name("SSL Context Service")
-  .details("Specified the SSL Context Service that can be used to create 
secure connections")
+  .description("Specified the SSL Context Service that can be used to create 
secure connections")
   .required(true)
   .identifiesControllerService(SSLContextService.class)
   .build();</code></pre>
@@ -3102,7 +3183,7 @@ worry about bothering us. Just ping the
 </div>
 <div id="footer">
 <div id="footer-text">
-Last updated 2015-12-08 13:53:16 -05:00
+Last updated 2016-02-16 10:19:45 EST
 </div>
 </div>
 </body>


Reply via email to