/*
* 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.toolkit.tls.service.client;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.apache.commons.cli.CommandLine;
import org.apache.nifi.toolkit.tls.commandLine.CommandLineParseException;
import org.apache.nifi.toolkit.tls.commandLine.ExitCode;
import org.apache.nifi.toolkit.tls.configuration.TlsClientConfig;
import org.apache.nifi.toolkit.tls.service.BaseCertificateAuthorityCommandLine;
import org.apache.nifi.toolkit.tls.util.InputStreamFactory;
import org.apache.nifi.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Command line parser for a TlsClientConfig object and a main entry point to invoke the parser and run the CA client
*/
public class TlsCertificateAuthorityClientCommandLine extends BaseCertificateAuthorityCommandLine {
public static final String DESCRIPTION = "Generates a private key and gets it signed by the certificate authority.";
public static final String CERTIFICATE_DIRECTORY = "certificateDirectory";
public static final String SUBJECT_ALTERNATIVE_NAMES = "subjectAlternativeNames";
public static final String DEFAULT_CERTIFICATE_DIRECTORY = ".";
private final Logger logger = LoggerFactory.getLogger(TlsCertificateAuthorityClientCommandLine.class);
private final InputStreamFactory inputStreamFactory;
private String certificateDirectory;
private String domainAlternativeNames;
public TlsCertificateAuthorityClientCommandLine() {
this(FileInputStream::new);
}
public TlsCertificateAuthorityClientCommandLine(InputStreamFactory inputStreamFactory) {
super(DESCRIPTION);
this.inputStreamFactory = inputStreamFactory;
addOptionWithArg("C", CERTIFICATE_DIRECTORY, "The file to write the CA certificate to", DEFAULT_CERTIFICATE_DIRECTORY);
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 {
TlsCertificateAuthorityClientCommandLine tlsCertificateAuthorityClientCommandLine = new TlsCertificateAuthorityClientCommandLine();
try {
tlsCertificateAuthorityClientCommandLine.parse(args);
} catch (CommandLineParseException e) {
System.exit(e.getExitCode().ordinal());
}
new TlsCertificateAuthorityClient().generateCertificateAndGetItSigned(tlsCertificateAuthorityClientCommandLine.createClientConfig(),
tlsCertificateAuthorityClientCommandLine.getCertificateDirectory(), tlsCertificateAuthorityClientCommandLine.getConfigJsonOut(),
tlsCertificateAuthorityClientCommandLine.differentPasswordForKeyAndKeystore());
System.exit(ExitCode.SUCCESS.ordinal());
}
@Override
protected boolean shouldAddDaysArg() {
return false;
}
@Override
protected boolean shouldAddSigningAlgorithmArg() {
return false;
}
@Override
protected String getTokenDescription() {
return "The token to use to prevent MITM (required and must be same as one used by CA)";
}
@Override
protected String getDnDescription() {
return "The dn to use for the client certificate";
}
@Override
protected String getPortDescription() {
return "The port to use to communicate with the Certificate Authority";
}
@Override
protected String getDnHostname() {
try {
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
logger.warn("Unable to determine hostname", e);
return "localhost";
}
}
@Override
protected CommandLine doParse(String[] args) throws CommandLineParseException {
CommandLine commandLine = super.doParse(args);
certificateDirectory = commandLine.getOptionValue(CERTIFICATE_DIRECTORY, DEFAULT_CERTIFICATE_DIRECTORY);
domainAlternativeNames = commandLine.getOptionValue(SUBJECT_ALTERNATIVE_NAMES);
return commandLine;
}
public String getCertificateDirectory() {
return certificateDirectory;
}
public String getDomainAlternativeNames() {
return domainAlternativeNames;
}
public TlsClientConfig createClientConfig() throws IOException {
String configJsonIn = getConfigJsonIn();
if (!StringUtils.isEmpty(configJsonIn)) {
try (InputStream inputStream = inputStreamFactory.create(new File(configJsonIn))) {
TlsClientConfig tlsClientConfig = new ObjectMapper().readValue(inputStream, TlsClientConfig.class);
tlsClientConfig.initDefaults();
return tlsClientConfig;
}
} else {
TlsClientConfig tlsClientConfig = new TlsClientConfig();
tlsClientConfig.setCaHostname(getCertificateAuthorityHostname());
tlsClientConfig.setDn(getDn());
tlsClientConfig.setDomainAlternativeNames(getDomainAlternativeNames());
tlsClientConfig.setToken(getToken());
tlsClientConfig.setPort(getPort());
tlsClientConfig.setKeyStore(KEYSTORE + getKeyStoreType().toLowerCase());
tlsClientConfig.setKeyStoreType(getKeyStoreType());
tlsClientConfig.setTrustStore(TRUSTSTORE + tlsClientConfig.getTrustStoreType().toLowerCase());
tlsClientConfig.setKeySize(getKeySize());
tlsClientConfig.setKeyPairAlgorithm(getKeyAlgorithm());
tlsClientConfig.setSigningAlgorithm(getSigningAlgorithm());
return tlsClientConfig;
}
}
}