forked from apache/nifi
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
NIFI-14001 Added Framework Support for PEM Keys and Certificates
- Loading branch information
1 parent
6c4ddf8
commit f44696a
Showing
21 changed files
with
1,358 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
...i-security-ssl/src/main/java/org/apache/nifi/security/ssl/InputStreamKeyStoreBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* | ||
* 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.security.ssl; | ||
|
||
import java.io.InputStream; | ||
|
||
/** | ||
* Extension of Key Store Builder supporting reading from an Input Stream | ||
*/ | ||
public interface InputStreamKeyStoreBuilder extends KeyStoreBuilder { | ||
/** | ||
* Set Key Store InputStream to be loaded | ||
* | ||
* @param inputStream Key Store InputStream | ||
* @return Builder | ||
*/ | ||
KeyStoreBuilder inputStream(InputStream inputStream); | ||
} |
92 changes: 92 additions & 0 deletions
92
...ecurity-ssl/src/main/java/org/apache/nifi/security/ssl/PemCertificateKeyStoreBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/* | ||
* 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.security.ssl; | ||
|
||
import java.io.InputStream; | ||
import java.security.KeyStore; | ||
import java.security.KeyStoreException; | ||
import java.security.cert.Certificate; | ||
import java.util.List; | ||
import java.util.Objects; | ||
|
||
/** | ||
* Key Store Builder capable of reading one or more X.509 Certificates formatted with PEM headers and footers | ||
*/ | ||
public class PemCertificateKeyStoreBuilder implements InputStreamKeyStoreBuilder { | ||
private static final String CERTIFICATE_ALIAS = "certificate-%d"; | ||
|
||
private InputStream inputStream; | ||
|
||
/** | ||
* Build Key Store using configured properties | ||
* | ||
* @return Key Store | ||
*/ | ||
@Override | ||
public KeyStore build() { | ||
final KeyStore keyStore = getInitializedKeyStore(); | ||
|
||
if (inputStream == null) { | ||
throw new BuilderConfigurationException("Key Store InputStream not configured"); | ||
} | ||
|
||
loadKeyStore(keyStore); | ||
|
||
return keyStore; | ||
} | ||
|
||
/** | ||
* Set Key Store InputStream to be loaded | ||
* | ||
* @param inputStream Key Store InputStream | ||
* @return Builder | ||
*/ | ||
@Override | ||
public PemCertificateKeyStoreBuilder inputStream(final InputStream inputStream) { | ||
this.inputStream = Objects.requireNonNull(inputStream, "Key Store InputStream required"); | ||
return this; | ||
} | ||
|
||
private void loadKeyStore(final KeyStore keyStore) { | ||
final PemCertificateReader pemCertificateReader = new StandardPemCertificateReader(); | ||
final List<Certificate> certificates = pemCertificateReader.readCertificates(inputStream); | ||
|
||
int certificateIndex = 0; | ||
for (final Certificate certificate : certificates) { | ||
final String alias = CERTIFICATE_ALIAS.formatted(certificateIndex++); | ||
|
||
try { | ||
keyStore.setCertificateEntry(alias, certificate); | ||
} catch (final KeyStoreException e) { | ||
final String message = String.format("Set certificate entry [%s] failed", alias); | ||
throw new BuilderConfigurationException(message, e); | ||
} | ||
} | ||
} | ||
|
||
private KeyStore getInitializedKeyStore() { | ||
final String keyStoreType = KeyStore.getDefaultType(); | ||
try { | ||
final KeyStore keyStore = KeyStore.getInstance(keyStoreType); | ||
keyStore.load(null); | ||
return keyStore; | ||
} catch (final Exception e) { | ||
final String message = String.format("Key Store Type [%s] initialization failed", keyStoreType); | ||
throw new BuilderConfigurationException(message, e); | ||
} | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
...ns/nifi-security-ssl/src/main/java/org/apache/nifi/security/ssl/PemCertificateReader.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. | ||
* The ASF licenses this file to You under the Apache License, Version 2.0 | ||
* (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.apache.nifi.security.ssl; | ||
|
||
import java.io.InputStream; | ||
import java.security.cert.Certificate; | ||
import java.util.List; | ||
|
||
/** | ||
* Abstraction for reading one or more Certificates from a stream containing PEM headers and footers | ||
*/ | ||
interface PemCertificateReader { | ||
/** | ||
* Read Certificates from stream of PEM sections | ||
* | ||
* @param inputStream Input Stream required | ||
* @return Parsed certificates or empty when none found | ||
*/ | ||
List<Certificate> readCertificates(InputStream inputStream); | ||
} |
108 changes: 108 additions & 0 deletions
108
...l/src/main/java/org/apache/nifi/security/ssl/PemPrivateKeyCertificateKeyStoreBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. | ||
* The ASF licenses this file to You under the Apache License, Version 2.0 | ||
* (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.apache.nifi.security.ssl; | ||
|
||
import java.io.InputStream; | ||
import java.security.KeyStore; | ||
import java.security.KeyStoreException; | ||
import java.security.PrivateKey; | ||
import java.security.cert.Certificate; | ||
import java.util.List; | ||
import java.util.Objects; | ||
|
||
/** | ||
* Key Store Builder capable of reading a Private Key and one or more X.509 Certificates formatted with PEM headers and footers | ||
*/ | ||
public class PemPrivateKeyCertificateKeyStoreBuilder implements KeyStoreBuilder { | ||
private static final String ALIAS = "private-key-1"; | ||
|
||
private static final char[] EMPTY_PROTECTION_PARAMETER = new char[]{}; | ||
|
||
private InputStream privateKeyInputStream; | ||
|
||
private InputStream certificateInputStream; | ||
|
||
/** | ||
* Build Key Store using configured properties | ||
* | ||
* @return Key Store | ||
*/ | ||
@Override | ||
public KeyStore build() { | ||
final KeyStore keyStore = getInitializedKeyStore(); | ||
|
||
if (certificateInputStream == null) { | ||
throw new BuilderConfigurationException("Certificate InputStream not configured"); | ||
} | ||
if (privateKeyInputStream == null) { | ||
throw new BuilderConfigurationException("Private Key InputStream not configured"); | ||
} | ||
|
||
loadKeyStore(keyStore); | ||
|
||
return keyStore; | ||
} | ||
|
||
/** | ||
* Set Certificate InputStream to be loaded | ||
* | ||
* @param certificateInputStream Certificate InputStream | ||
* @return Builder | ||
*/ | ||
public PemPrivateKeyCertificateKeyStoreBuilder certificateInputStream(final InputStream certificateInputStream) { | ||
this.certificateInputStream = Objects.requireNonNull(certificateInputStream, "Certificate InputStream required"); | ||
return this; | ||
} | ||
|
||
/** | ||
* Set Private Key InputStream to be loaded | ||
* | ||
* @param privateKeyInputStream Private Key InputStream | ||
* @return Builder | ||
*/ | ||
public PemPrivateKeyCertificateKeyStoreBuilder privateKeyInputStream(final InputStream privateKeyInputStream) { | ||
this.privateKeyInputStream = Objects.requireNonNull(privateKeyInputStream, "Private Key InputStream required"); | ||
return this; | ||
} | ||
|
||
private void loadKeyStore(final KeyStore keyStore) { | ||
final PemCertificateReader pemCertificateReader = new StandardPemCertificateReader(); | ||
final List<Certificate> certificates = pemCertificateReader.readCertificates(certificateInputStream); | ||
final Certificate[] certificateChain = certificates.toArray(new Certificate[]{}); | ||
|
||
final PemPrivateKeyReader pemPrivateKeyReader = new StandardPemPrivateKeyReader(); | ||
final PrivateKey privateKey = pemPrivateKeyReader.readPrivateKey(privateKeyInputStream); | ||
|
||
try { | ||
keyStore.setKeyEntry(ALIAS, privateKey, EMPTY_PROTECTION_PARAMETER, certificateChain); | ||
} catch (final KeyStoreException e) { | ||
throw new BuilderConfigurationException("Set key entry failed", e); | ||
} | ||
} | ||
|
||
private KeyStore getInitializedKeyStore() { | ||
final String keyStoreType = KeyStore.getDefaultType(); | ||
try { | ||
final KeyStore keyStore = KeyStore.getInstance(keyStoreType); | ||
keyStore.load(null); | ||
return keyStore; | ||
} catch (final Exception e) { | ||
final String message = String.format("Key Store Type [%s] initialization failed", keyStoreType); | ||
throw new BuilderConfigurationException(message, e); | ||
} | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
...ons/nifi-security-ssl/src/main/java/org/apache/nifi/security/ssl/PemPrivateKeyReader.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. | ||
* The ASF licenses this file to You under the Apache License, Version 2.0 | ||
* (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.apache.nifi.security.ssl; | ||
|
||
import java.io.InputStream; | ||
import java.security.PrivateKey; | ||
|
||
/** | ||
* Abstraction for reading a Private Key from a stream containing PEM headers and footers | ||
*/ | ||
interface PemPrivateKeyReader { | ||
/** | ||
* Read Private Key from stream | ||
* | ||
* @param inputStream Stream containing PEM header and footer | ||
* @return Private Key | ||
*/ | ||
PrivateKey readPrivateKey(InputStream inputStream); | ||
} |
41 changes: 41 additions & 0 deletions
41
...ons/nifi-security-ssl/src/main/java/org/apache/nifi/security/ssl/ReadEntityException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* | ||
* 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.security.ssl; | ||
|
||
/** | ||
* Exception indicating runtime failure to read specified entity | ||
*/ | ||
public class ReadEntityException extends RuntimeException { | ||
/** | ||
* Read Entity Exception Constructor with standard properties | ||
* | ||
* @param message Exception Message | ||
* @param cause Exception Cause | ||
*/ | ||
public ReadEntityException(final String message, final Throwable cause) { | ||
super(message, cause); | ||
} | ||
|
||
/** | ||
* Read Entity Exception Constructor without Throwable cause | ||
* | ||
* @param message Exception Message | ||
*/ | ||
public ReadEntityException(final String message) { | ||
super(message); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.