[
https://issues.apache.org/jira/browse/NIFI-1831?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15428998#comment-15428998
]
ASF GitHub Bot commented on NIFI-1831:
--------------------------------------
Github user alopresto commented on the issue:
https://github.com/apache/nifi/pull/834
@joewitt @mattyb149 @bbende @brosander
As of right now, this PR (commit `ffab01d`) is rebased against the latest
master. The tool is found in
`nifi-toolkit/nifi-toolkit-assembly/target/nifi-toolkit-1.0.0-SNAPSHOT-bin/nifi-toolkit-1.0.0-SNAPSHOT/`.
Running the command below (for example) will read an existing
_nifi.properties_ file, encrypt all sensitive non-empty values using the
provided _key_, populate those values (and the associated protection schemes --
`x.y.z.protected=aes/gcm/256`) into the new _nifi-encrypted.properties_ file,
and persist the key in _bootstrap.conf_.
* `$ ./bin/encrypt-config.sh -h` -- prints a usage message
* `$ ./bin/encrypt-config.sh -b path/to/bootstrap.conf -n
path/to/nifi.properties -o path/to/nifi-encrypted.properties -p
thisIsABadPropertiesPassword` -- normal use as described above
* `$ ./bin/encrypt-config.sh -b path/to/bootstrap.conf -n
path/to/nifi.properties -o path/to/nifi-encrypted.properties -k
0123456789ABCDEFFEDCBA98765432100123456789ABCDEFFEDCBA9876543210` -- normal use
as described above with raw hex key instead of password
* `$ ./bin/encrypt-config.sh -b path/to/bootstrap.conf -n
path/to/nifi.properties -o path/to/nifi-encrypted.properties` -- normal use as
described above but will prompt for key in secure console read
By default, it considers *sensitive* properties as anything that would be a
password or key:
* `nifi.sensitive.props.key`
* `nifi.security.keystorePasswd`
* `nifi.security.keyPasswd`
* `nifi.security.truststorePasswd`
You can mark additional keys as *sensitive* by including them in a comma or
semi-colon delimited string as follows (do this by hand in the input
_nifi.properties_ before running the tool):
`nifi.sensitive.props.additional.keys=nifi.ui.banner.text`
Example:
*before* -- `~/Workspace/scratch/encrypted-configs/nifi.properties`
```
nifi.ui.banner.text=This is the banner text
...
# security properties #
nifi.sensitive.props.key=
nifi.sensitive.props.algorithm=PBEWITHMD5AND256BITAES-CBC-OPENSSL
nifi.sensitive.props.provider=BC
nifi.sensitive.props.additional.keys=nifi.ui.banner.text
nifi.security.keystore=keystore.jks
nifi.security.keystoreType=jks
nifi.security.keystorePasswd=thisIsABadKeystorePassword
nifi.security.keyPasswd=thisIsABadKeyPassword
nifi.security.truststore=truststore.jks
nifi.security.truststoreType=jks
nifi.security.truststorePasswd=thisIsABadTruststorePassword
nifi.security.needClientAuth=
nifi.security.user.authorizer=file-provider
nifi.security.user.login.identity.provider=
nifi.security.ocsp.responder.url=
nifi.security.ocsp.responder.certificate=
...
```
*run tool* --
```
hw12203:...assembly/target/nifi-toolkit-1.0.0-SNAPSHOT-bin/nifi-toolkit-1.0.0-SNAPSHOT
(NIFI-1831) alopresto
🔓 167s @ 15:49:34 $ ./bin/encrypt-config.sh -b
~/Workspace/scratch/encrypted-configs/bootstrap.conf -n
~/Workspace/scratch/encrypted-configs/nifi.properties -o
~/Workspace/scratch/encrypted-configs/nifi-encrypted.properties -p
thisIsABadPropertiesPassword
2016-08-19 15:57:48,097 INFO [main]
o.a.nifi.properties.ConfigEncryptionTool Invoked ConfigEncryptionTool with args
[-b,/Users/alopresto/Workspace/scratch/encrypted-configs/bootstrap.conf,-n,/Users/alopresto/Workspace/scratch/encrypted-configs/nifi.properties,-o,/Users/alopresto/Workspace/scratch/encrypted-configs/nifi-encrypted.properties,-p,thisIsABadPropertiesPassword]
2016-08-19 15:57:48,794 INFO [main]
o.a.nifi.properties.NiFiPropertiesLoader Loaded 112 properties from
/Users/alopresto/Workspace/scratch/encrypted-configs/nifi.properties
2016-08-19 15:57:48,796 INFO [main]
o.a.n.properties.ProtectedNiFiProperties Loaded 112 properties (including 0
protection schemes) into ProtectedNiFiProperties
2016-08-19 15:57:48,800 INFO [main]
o.a.nifi.properties.ConfigEncryptionTool Loaded NiFiProperties instance with
112 properties
2016-08-19 15:57:48,805 INFO [main]
o.a.n.properties.ProtectedNiFiProperties Loaded 112 properties (including 0
protection schemes) into ProtectedNiFiProperties
2016-08-19 15:57:49,149 INFO [main] o.a.n.p.AESSensitivePropertyProvider
AES Sensitive Property Provider encrypted a sensitive value successfully
2016-08-19 15:57:49,151 INFO [main]
o.a.nifi.properties.ConfigEncryptionTool Protected nifi.ui.banner.text with
aes/gcm/256 ->
2ZJZaFqqXl62HB5w||I57IDLE7hYJf2vJmrkC29ZjDztRJT00CVV1QkDiGte4VIfUB+n2X
2016-08-19 15:57:49,152 INFO [main]
o.a.nifi.properties.ConfigEncryptionTool Updated protection key
nifi.ui.banner.text.protected
2016-08-19 15:57:49,152 INFO [main] o.a.n.p.AESSensitivePropertyProvider
AES Sensitive Property Provider encrypted a sensitive value successfully
2016-08-19 15:57:49,152 INFO [main]
o.a.nifi.properties.ConfigEncryptionTool Protected nifi.security.keyPasswd with
aes/gcm/256 ->
icyABIxwN8FBBd6Q||GL+I6P5tv4ThiVXcAYkFaPsQLK2jZHyJui02W2YxydXfA0sEfg
2016-08-19 15:57:49,152 INFO [main]
o.a.nifi.properties.ConfigEncryptionTool Updated protection key
nifi.security.keyPasswd.protected
2016-08-19 15:57:49,152 INFO [main] o.a.n.p.AESSensitivePropertyProvider
AES Sensitive Property Provider encrypted a sensitive value successfully
2016-08-19 15:57:49,153 INFO [main]
o.a.nifi.properties.ConfigEncryptionTool Protected nifi.security.keystorePasswd
with aes/gcm/256 ->
eXpm2ylPEzfxpnEz||5Iqj7wReXHudmu/q7/q4vj2ooxFGN0R+o4VjV0BjboZ7zD6tqIEX3/Eq
2016-08-19 15:57:49,153 INFO [main]
o.a.nifi.properties.ConfigEncryptionTool Updated protection key
nifi.security.keystorePasswd.protected
2016-08-19 15:57:49,153 INFO [main] o.a.n.p.AESSensitivePropertyProvider
AES Sensitive Property Provider encrypted a sensitive value successfully
2016-08-19 15:57:49,153 INFO [main]
o.a.nifi.properties.ConfigEncryptionTool Protected
nifi.security.truststorePasswd with aes/gcm/256 ->
LGB8TUHtBTHemkzF||J5IqJpEB2i6QlFRqCEvgdq0koNPJv/oV4i3znyoAfzUV4laNv3TmWkeHFfs
2016-08-19 15:57:49,153 INFO [main]
o.a.nifi.properties.ConfigEncryptionTool Updated protection key
nifi.security.truststorePasswd.protected
2016-08-19 15:57:49,167 INFO [main]
o.a.n.properties.ProtectedNiFiProperties Loaded 115 properties (including 4
protection schemes) into ProtectedNiFiProperties
2016-08-19 15:57:49,167 INFO [main]
o.a.nifi.properties.ConfigEncryptionTool Final result: 115 keys including 4
protected keys
2016-08-19 15:57:49,195 INFO [main]
o.a.n.properties.ProtectedNiFiProperties Loaded 115 properties (including 4
protection schemes) into ProtectedNiFiProperties
hw12203:...assembly/target/nifi-toolkit-1.0.0-SNAPSHOT-bin/nifi-toolkit-1.0.0-SNAPSHOT
(NIFI-1831) alopresto
🔓 495s @ 15:57:50 $
```
*after* -- `nifi-encrypted.properties`
```
nifi.ui.banner.text=2ZJZaFqqXl62HB5w||I57IDLE7hYJf2vJmrkC29ZjDztRJT00CVV1QkDiGte4VIfUB+n2X
nifi.ui.banner.text.protected=aes/gcm/256
...
# security properties #
nifi.sensitive.props.key=
nifi.sensitive.props.algorithm=PBEWITHMD5AND256BITAES-CBC-OPENSSL
nifi.sensitive.props.provider=BC
nifi.sensitive.props.additional.keys=nifi.ui.banner.text
nifi.security.keystore=keystore.jks
nifi.security.keystoreType=jks
nifi.security.keystorePasswd=eXpm2ylPEzfxpnEz||5Iqj7wReXHudmu/q7/q4vj2ooxFGN0R+o4VjV0BjboZ7zD6tqIEX3/Eq
nifi.security.keystorePasswd.protected=aes/gcm/256
nifi.security.keyPasswd=icyABIxwN8FBBd6Q||GL+I6P5tv4ThiVXcAYkFaPsQLK2jZHyJui02W2YxydXfA0sEfg
nifi.security.keyPasswd.protected=aes/gcm/256
nifi.security.truststore=truststore.jks
nifi.security.truststoreType=jks
nifi.security.truststorePasswd=LGB8TUHtBTHemkzF||J5IqJpEB2i6QlFRqCEvgdq0koNPJv/oV4i3znyoAfzUV4laNv3TmWkeHFfs
nifi.security.truststorePasswd.protected=aes/gcm/256
nifi.security.needClientAuth=
nifi.security.user.authorizer=file-provider
nifi.security.user.login.identity.provider=
nifi.security.ocsp.responder.url=
nifi.security.ocsp.responder.certificate=
```
I am still working on a couple small features like handling secure password
entry to the console instead of just the key (and *then will remove the
debugging of the invocation parameters which includes the key/password*).
Please exercise what is here and report any issues. Thanks.
> Allow encrypted passwords in configuration files
> ------------------------------------------------
>
> Key: NIFI-1831
> URL: https://issues.apache.org/jira/browse/NIFI-1831
> Project: Apache NiFi
> Issue Type: New Feature
> Components: Configuration, Core Framework
> Affects Versions: 0.6.1
> Reporter: Andy LoPresto
> Assignee: Andy LoPresto
> Priority: Critical
> Labels: configuration, encryption, password, security
> Fix For: 1.0.0
>
> Original Estimate: 504h
> Remaining Estimate: 504h
>
> Storing passwords in plaintext in configuration files is not a security best
> practice. While file access can be restricted through OS permissions, these
> configuration files can be accidentally checked into source control, shared
> or deployed to multiple instances, etc.
> NiFi should allow a deployer to provide an encrypted password in the
> configuration file to minimize exposure of the passwords. On application
> start-up, NiFi should decrypt the passwords in memory. NiFi should also
> include a utility to encrypt the raw passwords (and optionally populate the
> configuration files and provide additional metadata in the configuration
> files).
> I am aware this simply shifts the responsibility/delegation of trust from the
> passwords in the properties file to a new location on the same system, but
> mitigating the visibility of the raw passwords in the properties file can be
> one step in a defense in depth approach and is often mandated by security
> policies within organizations using NiFi.
> The key used for encryption should not be hard-coded into the application
> source code, nor should it be universally consistent. The key could be
> determined by reading static information from the deployed system and feeding
> it to a key derivation function based on a cryptographically-secure hash
> function, such as PBKDF2, bcrypt, or scrypt. However, this does introduce
> upgrade, system migration, and portability issues. These challenges will have
> to be kept in consideration when determining the key derivation process.
> Manual key entry is a possibility, and then the master key would only be
> present in memory, but this prevents automatic reboot on loss of power or
> other recovery scenario.
> This must be backward-compatible to allow systems with plaintext passwords to
> continue operating. Options for achieving this are to only attempt to decrypt
> passwords when a sibling property is present, or to match a specific format.
> For these examples, I have used the following default values:
> {code}
> password: thisIsABadPassword
> key: 0123456789ABCDEFFEDCBA98765432100123456789ABCDEFFEDCBA9876543210
> iv: 0123456789ABCDEFFEDCBA9876543210
> algorithm: AES/CBC 256-bit
> {code}
> **Note: These values should not be used in production systems -- the key and
> IV are common test values, and an AEAD cipher is preferable to provide cipher
> text integrity assurances, however OpenSSL does not support the use of AEAD
> ciphers for command-line encryption at this time**
> Example 1: *here the sibling property indicates the password is encrypted and
> with which implementation; the absence of the property would default to a raw
> password*
> {code}
> hw12203:/Users/alopresto/Workspace/scratch/encrypted-passwords (master)
> alopresto
> 🔓 0s @ 16:25:56 $ echo "thisIsABadPassword" > password.txt
> hw12203:/Users/alopresto/Workspace/scratch/encrypted-passwords (master)
> alopresto
> 🔓 0s @ 16:26:47 $ ossl aes-256-cbc -e -nosalt -p -K
> 0123456789ABCDEFFEDCBA98765432100123456789ABCDEFFEDCBA9876543210 -iv
> 0123456789ABCDEFFEDCBA9876543210 -a -in password.txt -out password.enc
> key=0123456789ABCDEFFEDCBA98765432100123456789ABCDEFFEDCBA9876543210
> iv =0123456789ABCDEFFEDCBA9876543210
> hw12203:/Users/alopresto/Workspace/scratch/encrypted-passwords (master)
> alopresto
> 🔓 0s @ 16:27:09 $ xxd password.enc
> 0000000: 5643 5856 6146 6250 4158 364f 5743 7646 VCXVaFbPAX6OWCvF
> 0000010: 6963 6b76 4a63 7744 3854 6b67 3731 4c76 ickvJcwD8Tkg71Lv
> 0000020: 4d38 6d32 7952 4776 5739 413d 0a M8m2yRGvW9A=.
> hw12203:/Users/alopresto/Workspace/scratch/encrypted-passwords (master)
> alopresto
> 🔓 0s @ 16:27:16 $ more password.enc
> VCXVaFbPAX6OWCvFickvJcwD8Tkg71LvM8m2yRGvW9A=
> hw12203:/Users/alopresto/Workspace/scratch/encrypted-passwords (master)
> alopresto
> 🔓 0s @ 16:27:55 $
> {code}
> In {{nifi.properties}}:
> {code}
> nifi.security.keystorePasswd=VCXVaFbPAX6OWCvFickvJcwD8Tkg71LvM8m2yRGvW9A=
> nifi.security.keystorePasswd.encrypted=AES-CBC-256
> {code}
> Example 2: *here the encrypted password has a header tag indicating both that
> it is encrypted and the algorithm used*
> {code:java}
> @Test
> public void testShouldDecryptPassword() throws Exception {
> // Arrange
> KeyedCipherProvider cipherProvider = new AESKeyedCipherProvider()
> final String PLAINTEXT = "thisIsABadPassword"
> logger.info("Expected: ${Hex.encodeHexString(PLAINTEXT.bytes)}")
> final byte[] IV = Hex.decodeHex("0123456789ABCDEFFEDCBA9876543210" as
> char[])
> final byte[] LOCAL_KEY =
> Hex.decodeHex("0123456789ABCDEFFEDCBA9876543210" * 2 as char[])
> // Generated via openssl enc -a
> final String CIPHER_TEXT =
> "VCXVaFbPAX6OWCvFickvJcwD8Tkg71LvM8m2yRGvW9A="
> byte[] cipherBytes = Base64.decoder.decode(CIPHER_TEXT)
> SecretKey localKey = new SecretKeySpec(LOCAL_KEY, "AES")
> EncryptionMethod encryptionMethod = EncryptionMethod.AES_CBC
> logger.info("Using algorithm: ${encryptionMethod.getAlgorithm()}")
> logger.info("Cipher text: \$nifipw\$${CIPHER_TEXT}
> ${cipherBytes.length + 8}")
> // Act
> Cipher cipher = cipherProvider.getCipher(encryptionMethod, localKey,
> IV, false)
> byte[] recoveredBytes = cipher.doFinal(cipherBytes)
>
> // OpenSSL adds a newline character during encryption
> String recovered = new String(recoveredBytes, "UTF-8").trim()
> logger.info("Recovered: ${recovered}
> ${Hex.encodeHexString(recoveredBytes)}")
> // Assert
> assert PLAINTEXT.equals(recovered)
> }
> {code}
> In {{nifi.properties}}:
> {code}
> nifi.security.keystorePasswd=$nifipw$VCXVaFbPAX6OWCvFickvJcwD8Tkg71LvM8m2yRGvW9A=
> {code}
> Ideally, NiFi would use a pluggable implementation architecture to allow
> users to integrate with a variety of secret management services. There are
> both commercial and open source solutions, including CyberArk Enterprise
> Password Vault [1], Hashicorp Vault [2], and Square Keywhiz [3]. In the
> future, this could also be extended to Hardware Security Modules (HSM) like
> SafeNet Luna [4] and Amazon CloudHSM [5].
> [1]
> http://www.cyberark.com/products/privileged-account-security-solution/enterprise-password-vault/
> [2] https://www.vaultproject.io/
> [3] https://square.github.io/keywhiz/
> [4]
> http://www.safenet-inc.com/data-encryption/hardware-security-modules-hsms/luna-hsms-key-management/luna-sa-network-hsm/
> [5] https://aws.amazon.com/cloudhsm/
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)