mirror of https://github.com/apache/nifi.git
NIFI-3490 added SAN option for TLS toolkit in standalone mode
This closes #1530. Signed-off-by: Andy LoPresto <alopresto@apache.org>
This commit is contained in:
parent
b7f946e847
commit
bf112d0654
|
@ -44,6 +44,7 @@ public class TlsClientConfig extends TlsConfig {
|
||||||
setDnPrefix(tlsConfig.getDnPrefix());
|
setDnPrefix(tlsConfig.getDnPrefix());
|
||||||
setDnSuffix(tlsConfig.getDnSuffix());
|
setDnSuffix(tlsConfig.getDnSuffix());
|
||||||
setReorderDn(tlsConfig.getReorderDn());
|
setReorderDn(tlsConfig.getReorderDn());
|
||||||
|
setDomainAlternativeNames(tlsConfig.getDomainAlternativeNames());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ public class TlsCertificateAuthorityClientCommandLine extends BaseCertificateAut
|
||||||
super(DESCRIPTION);
|
super(DESCRIPTION);
|
||||||
this.inputStreamFactory = inputStreamFactory;
|
this.inputStreamFactory = inputStreamFactory;
|
||||||
addOptionWithArg("C", CERTIFICATE_DIRECTORY, "The file to write the CA certificate to", DEFAULT_CERTIFICATE_DIRECTORY);
|
addOptionWithArg("C", CERTIFICATE_DIRECTORY, "The file to write the CA certificate to", DEFAULT_CERTIFICATE_DIRECTORY);
|
||||||
addOptionWithArg("S", SUBJECT_ALTERNATIVE_NAMES, "Comma-separated list of domains to use as Subject Alternative Names in the certificate");
|
addOptionWithArg(null, SUBJECT_ALTERNATIVE_NAMES, "Comma-separated list of domains to use as Subject Alternative Names in the certificate");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
package org.apache.nifi.toolkit.tls.standalone;
|
package org.apache.nifi.toolkit.tls.standalone;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.nifi.security.util.CertificateUtils;
|
import org.apache.nifi.security.util.CertificateUtils;
|
||||||
import org.apache.nifi.security.util.KeystoreType;
|
import org.apache.nifi.security.util.KeystoreType;
|
||||||
import org.apache.nifi.security.util.KeyStoreUtils;
|
import org.apache.nifi.security.util.KeyStoreUtils;
|
||||||
|
@ -29,6 +30,7 @@ import org.apache.nifi.toolkit.tls.manager.writer.NifiPropertiesTlsClientConfigW
|
||||||
import org.apache.nifi.toolkit.tls.properties.NiFiPropertiesWriterFactory;
|
import org.apache.nifi.toolkit.tls.properties.NiFiPropertiesWriterFactory;
|
||||||
import org.apache.nifi.toolkit.tls.util.OutputStreamFactory;
|
import org.apache.nifi.toolkit.tls.util.OutputStreamFactory;
|
||||||
import org.apache.nifi.toolkit.tls.util.TlsHelper;
|
import org.apache.nifi.toolkit.tls.util.TlsHelper;
|
||||||
|
import org.bouncycastle.asn1.x509.Extensions;
|
||||||
import org.bouncycastle.openssl.jcajce.JcaMiscPEMGenerator;
|
import org.bouncycastle.openssl.jcajce.JcaMiscPEMGenerator;
|
||||||
import org.bouncycastle.util.io.pem.PemWriter;
|
import org.bouncycastle.util.io.pem.PemWriter;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -179,8 +181,10 @@ public class TlsToolkitStandalone {
|
||||||
tlsClientConfig.setTrustStorePassword(instanceDefinition.getTrustStorePassword());
|
tlsClientConfig.setTrustStorePassword(instanceDefinition.getTrustStorePassword());
|
||||||
TlsClientManager tlsClientManager = new TlsClientManager(tlsClientConfig);
|
TlsClientManager tlsClientManager = new TlsClientManager(tlsClientConfig);
|
||||||
KeyPair keyPair = TlsHelper.generateKeyPair(keyPairAlgorithm, keySize);
|
KeyPair keyPair = TlsHelper.generateKeyPair(keyPairAlgorithm, keySize);
|
||||||
|
Extensions sanDnsExtensions = StringUtils.isBlank(tlsClientConfig.getDomainAlternativeNames())
|
||||||
|
? null : TlsHelper.createDomainAlternativeNamesExtensions(tlsClientConfig.getDomainAlternativeNames());
|
||||||
tlsClientManager.addPrivateKeyToKeyStore(keyPair, NIFI_KEY, CertificateUtils.generateIssuedCertificate(tlsClientConfig.calcDefaultDn(hostname),
|
tlsClientManager.addPrivateKeyToKeyStore(keyPair, NIFI_KEY, CertificateUtils.generateIssuedCertificate(tlsClientConfig.calcDefaultDn(hostname),
|
||||||
keyPair.getPublic(), null, certificate, caKeyPair, signingAlgorithm, days), certificate);
|
keyPair.getPublic(), sanDnsExtensions, certificate, caKeyPair, signingAlgorithm, days), certificate);
|
||||||
tlsClientManager.setCertificateEntry(NIFI_CERT, certificate);
|
tlsClientManager.setCertificateEntry(NIFI_CERT, certificate);
|
||||||
tlsClientManager.addClientConfigurationWriter(new NifiPropertiesTlsClientConfigWriter(niFiPropertiesWriterFactory, new File(hostDir, "nifi.properties"),
|
tlsClientManager.addClientConfigurationWriter(new NifiPropertiesTlsClientConfigWriter(niFiPropertiesWriterFactory, new File(hostDir, "nifi.properties"),
|
||||||
hostname, instanceDefinition.getNumber()));
|
hostname, instanceDefinition.getNumber()));
|
||||||
|
|
|
@ -29,6 +29,7 @@ import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.apache.commons.cli.CommandLine;
|
import org.apache.commons.cli.CommandLine;
|
||||||
import org.apache.nifi.toolkit.tls.commandLine.BaseCommandLine;
|
import org.apache.nifi.toolkit.tls.commandLine.BaseCommandLine;
|
||||||
import org.apache.nifi.toolkit.tls.commandLine.CommandLineParseException;
|
import org.apache.nifi.toolkit.tls.commandLine.CommandLineParseException;
|
||||||
|
@ -58,6 +59,7 @@ public class TlsToolkitStandaloneCommandLine extends BaseCommandLine {
|
||||||
public static final String GLOBAL_PORT_SEQUENCE_ARG = "globalPortSequence";
|
public static final String GLOBAL_PORT_SEQUENCE_ARG = "globalPortSequence";
|
||||||
public static final String NIFI_DN_PREFIX_ARG = "nifiDnPrefix";
|
public static final String NIFI_DN_PREFIX_ARG = "nifiDnPrefix";
|
||||||
public static final String NIFI_DN_SUFFIX_ARG = "nifiDnSuffix";
|
public static final String NIFI_DN_SUFFIX_ARG = "nifiDnSuffix";
|
||||||
|
public static final String SUBJECT_ALTERNATIVE_NAMES = "subjectAlternativeNames";
|
||||||
|
|
||||||
public static final String DEFAULT_OUTPUT_DIRECTORY = calculateDefaultOutputDirectory(Paths.get("."));
|
public static final String DEFAULT_OUTPUT_DIRECTORY = calculateDefaultOutputDirectory(Paths.get("."));
|
||||||
|
|
||||||
|
@ -86,6 +88,7 @@ public class TlsToolkitStandaloneCommandLine extends BaseCommandLine {
|
||||||
private boolean overwrite;
|
private boolean overwrite;
|
||||||
private String dnPrefix;
|
private String dnPrefix;
|
||||||
private String dnSuffix;
|
private String dnSuffix;
|
||||||
|
private String domainAlternativeNames;
|
||||||
|
|
||||||
public TlsToolkitStandaloneCommandLine() {
|
public TlsToolkitStandaloneCommandLine() {
|
||||||
this(new PasswordUtil());
|
this(new PasswordUtil());
|
||||||
|
@ -104,6 +107,7 @@ public class TlsToolkitStandaloneCommandLine extends BaseCommandLine {
|
||||||
addOptionWithArg("B", CLIENT_CERT_PASSWORD_ARG, "Password for client certificate. Must either be one value or one for each client DN. (autogenerate if not specified)");
|
addOptionWithArg("B", CLIENT_CERT_PASSWORD_ARG, "Password for client certificate. Must either be one value or one for each client DN. (autogenerate if not specified)");
|
||||||
addOptionWithArg("G", GLOBAL_PORT_SEQUENCE_ARG, "Use sequential ports that are calculated for all hosts according to the provided hostname expressions. " +
|
addOptionWithArg("G", GLOBAL_PORT_SEQUENCE_ARG, "Use sequential ports that are calculated for all hosts according to the provided hostname expressions. " +
|
||||||
"(Can be specified multiple times, MUST BE SAME FROM RUN TO RUN.)");
|
"(Can be specified multiple times, MUST BE SAME FROM RUN TO RUN.)");
|
||||||
|
addOptionWithArg(null, SUBJECT_ALTERNATIVE_NAMES, "Comma-separated list of domains to use as Subject Alternative Names in the certificate");
|
||||||
addOptionWithArg(null, NIFI_DN_PREFIX_ARG, "String to prepend to hostname(s) when determining DN.", TlsConfig.DEFAULT_DN_PREFIX);
|
addOptionWithArg(null, NIFI_DN_PREFIX_ARG, "String to prepend to hostname(s) when determining DN.", TlsConfig.DEFAULT_DN_PREFIX);
|
||||||
addOptionWithArg(null, NIFI_DN_SUFFIX_ARG, "String to append to hostname(s) when determining DN.", TlsConfig.DEFAULT_DN_SUFFIX);
|
addOptionWithArg(null, NIFI_DN_SUFFIX_ARG, "String to append to hostname(s) when determining DN.", TlsConfig.DEFAULT_DN_SUFFIX);
|
||||||
addOptionNoArg("O", OVERWRITE_ARG, "Overwrite existing host output.");
|
addOptionNoArg("O", OVERWRITE_ARG, "Overwrite existing host output.");
|
||||||
|
@ -133,6 +137,7 @@ public class TlsToolkitStandaloneCommandLine extends BaseCommandLine {
|
||||||
|
|
||||||
dnPrefix = commandLine.getOptionValue(NIFI_DN_PREFIX_ARG, TlsConfig.DEFAULT_DN_PREFIX);
|
dnPrefix = commandLine.getOptionValue(NIFI_DN_PREFIX_ARG, TlsConfig.DEFAULT_DN_PREFIX);
|
||||||
dnSuffix = commandLine.getOptionValue(NIFI_DN_SUFFIX_ARG, TlsConfig.DEFAULT_DN_SUFFIX);
|
dnSuffix = commandLine.getOptionValue(NIFI_DN_SUFFIX_ARG, TlsConfig.DEFAULT_DN_SUFFIX);
|
||||||
|
domainAlternativeNames = commandLine.getOptionValue(SUBJECT_ALTERNATIVE_NAMES);
|
||||||
|
|
||||||
Stream<String> globalOrderExpressions = null;
|
Stream<String> globalOrderExpressions = null;
|
||||||
if (commandLine.hasOption(GLOBAL_PORT_SEQUENCE_ARG)) {
|
if (commandLine.hasOption(GLOBAL_PORT_SEQUENCE_ARG)) {
|
||||||
|
@ -228,6 +233,7 @@ public class TlsToolkitStandaloneCommandLine extends BaseCommandLine {
|
||||||
standaloneConfig.setDays(getDays());
|
standaloneConfig.setDays(getDays());
|
||||||
standaloneConfig.setDnPrefix(dnPrefix);
|
standaloneConfig.setDnPrefix(dnPrefix);
|
||||||
standaloneConfig.setDnSuffix(dnSuffix);
|
standaloneConfig.setDnSuffix(dnSuffix);
|
||||||
|
standaloneConfig.setDomainAlternativeNames(domainAlternativeNames);
|
||||||
standaloneConfig.initDefaults();
|
standaloneConfig.initDefaults();
|
||||||
|
|
||||||
return standaloneConfig;
|
return standaloneConfig;
|
||||||
|
|
|
@ -34,13 +34,16 @@ import java.security.cert.CertificateException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
|
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
|
||||||
import org.bouncycastle.asn1.x500.X500Name;
|
import org.bouncycastle.asn1.x500.X500Name;
|
||||||
import org.bouncycastle.asn1.x509.Extension;
|
import org.bouncycastle.asn1.x509.Extension;
|
||||||
|
import org.bouncycastle.asn1.x509.Extensions;
|
||||||
import org.bouncycastle.asn1.x509.ExtensionsGenerator;
|
import org.bouncycastle.asn1.x509.ExtensionsGenerator;
|
||||||
import org.bouncycastle.asn1.x509.GeneralName;
|
import org.bouncycastle.asn1.x509.GeneralName;
|
||||||
import org.bouncycastle.asn1.x509.GeneralNames;
|
import org.bouncycastle.asn1.x509.GeneralNames;
|
||||||
|
@ -198,15 +201,7 @@ public class TlsHelper {
|
||||||
// add Subject Alternative Name(s)
|
// add Subject Alternative Name(s)
|
||||||
if(StringUtils.isNotBlank(domainAlternativeNames)) {
|
if(StringUtils.isNotBlank(domainAlternativeNames)) {
|
||||||
try {
|
try {
|
||||||
List<GeneralName> namesList = new ArrayList<>();
|
jcaPKCS10CertificationRequestBuilder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, createDomainAlternativeNamesExtensions(domainAlternativeNames));
|
||||||
for(String alternativeName : domainAlternativeNames.split(",")) {
|
|
||||||
namesList.add(new GeneralName(GeneralName.dNSName, alternativeName));
|
|
||||||
}
|
|
||||||
|
|
||||||
GeneralNames subjectAltNames = new GeneralNames(namesList.toArray(new GeneralName [] {}));
|
|
||||||
ExtensionsGenerator extGen = new ExtensionsGenerator();
|
|
||||||
extGen.addExtension(Extension.subjectAlternativeName, false, subjectAltNames);
|
|
||||||
jcaPKCS10CertificationRequestBuilder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, extGen.generate());
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new OperatorCreationException("Error while adding " + domainAlternativeNames + " as Subject Alternative Name.", e);
|
throw new OperatorCreationException("Error while adding " + domainAlternativeNames + " as Subject Alternative Name.", e);
|
||||||
}
|
}
|
||||||
|
@ -215,4 +210,17 @@ public class TlsHelper {
|
||||||
JcaContentSignerBuilder jcaContentSignerBuilder = new JcaContentSignerBuilder(signingAlgorithm);
|
JcaContentSignerBuilder jcaContentSignerBuilder = new JcaContentSignerBuilder(signingAlgorithm);
|
||||||
return new JcaPKCS10CertificationRequest(jcaPKCS10CertificationRequestBuilder.build(jcaContentSignerBuilder.build(keyPair.getPrivate())));
|
return new JcaPKCS10CertificationRequest(jcaPKCS10CertificationRequestBuilder.build(jcaContentSignerBuilder.build(keyPair.getPrivate())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Extensions createDomainAlternativeNamesExtensions(String domainAlternativeNames) throws IOException {
|
||||||
|
List<GeneralName> namesList = new ArrayList<>();
|
||||||
|
for(String alternativeName : domainAlternativeNames.split(",")) {
|
||||||
|
namesList.add(new GeneralName(GeneralName.dNSName, alternativeName));
|
||||||
|
}
|
||||||
|
|
||||||
|
GeneralNames subjectAltNames = new GeneralNames(namesList.toArray(new GeneralName [] {}));
|
||||||
|
ExtensionsGenerator extGen = new ExtensionsGenerator();
|
||||||
|
extGen.addExtension(Extension.subjectAlternativeName, false, subjectAltNames);
|
||||||
|
return extGen.generate();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,13 @@ public class TlsToolkitStandaloneCommandLineTest {
|
||||||
assertEquals(testSigningAlgorithm, tlsToolkitStandaloneCommandLine.createConfig().getSigningAlgorithm());
|
assertEquals(testSigningAlgorithm, tlsToolkitStandaloneCommandLine.createConfig().getSigningAlgorithm());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSAN() throws CommandLineParseException, IOException {
|
||||||
|
String dnsSAN = "nifi.apache.org";
|
||||||
|
tlsToolkitStandaloneCommandLine.parse("--subjectAlternativeNames", dnsSAN);
|
||||||
|
assertEquals(dnsSAN, tlsToolkitStandaloneCommandLine.createConfig().getDomainAlternativeNames());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDaysNotInteger() {
|
public void testDaysNotInteger() {
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Reference in New Issue