[
https://issues.apache.org/jira/browse/NIFI-2193?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15398703#comment-15398703
]
ASF GitHub Bot commented on NIFI-2193:
--------------------------------------
Github user alopresto commented on a diff in the pull request:
https://github.com/apache/nifi/pull/695#discussion_r72741115
--- Diff:
nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/service/TlsCertificateSigningRequestPerformer.java
---
@@ -0,0 +1,144 @@
+/*
+ * 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;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.BoundedInputStream;
+import org.apache.http.HttpHost;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
+import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.apache.nifi.toolkit.tls.configuration.TlsClientConfig;
+import org.apache.nifi.toolkit.tls.util.TlsHelper;
+import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest;
+import org.eclipse.jetty.server.Response;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Supplier;
+
+public class TlsCertificateSigningRequestPerformer {
+ public static final String RECEIVED_RESPONSE_CODE = "Received response
code ";
+ public static final String EXPECTED_ONE_CERTIFICATE = "Expected one
certificate";
+ public static final String EXPECTED_RESPONSE_TO_CONTAIN_HMAC =
"Expected response to contain hmac";
+ public static final String
UNEXPECTED_HMAC_RECEIVED_POSSIBLE_MAN_IN_THE_MIDDLE = "Unexpected hmac
received, possible man in the middle";
+ public static final String EXPECTED_RESPONSE_TO_CONTAIN_CERTIFICATE =
"Expected response to contain certificate";
+ private final Supplier<HttpClientBuilder> httpClientBuilderSupplier;
+ private final String caHostname;
+ private final String dn;
+ private final String token;
+ private final int port;
+ private final TlsHelper tlsHelper;
+
+ public TlsCertificateSigningRequestPerformer(TlsClientConfig
tlsClientConfig) throws NoSuchAlgorithmException {
+ this(HttpClientBuilder::create, tlsClientConfig.getCaHostname(),
tlsClientConfig.getDn(), tlsClientConfig.getToken(), tlsClientConfig.getPort(),
tlsClientConfig.createTlsHelper());
+ }
+
+ public
TlsCertificateSigningRequestPerformer(Supplier<HttpClientBuilder>
httpClientBuilderSupplier, TlsClientConfig tlsClientConfig) throws
NoSuchAlgorithmException {
+ this(httpClientBuilderSupplier, tlsClientConfig.getCaHostname(),
tlsClientConfig.getDn(), tlsClientConfig.getToken(), tlsClientConfig.getPort(),
tlsClientConfig.createTlsHelper());
+ }
+
+ public
TlsCertificateSigningRequestPerformer(Supplier<HttpClientBuilder>
httpClientBuilderSupplier, String caHostname, String dn, String token, int
port, TlsHelper tlsHelper) {
+ this.httpClientBuilderSupplier = httpClientBuilderSupplier;
+ this.caHostname = caHostname;
+ this.dn = dn;
+ this.token = token;
+ this.port = port;
+ this.tlsHelper = tlsHelper;
+ }
+
+ public static String getDn(String hostname) {
+ return "CN=" + hostname + ",OU=NIFI";
+ }
+
+ /**
+ * Submits a CSR to the Certificate authority, checks the resulting
hmac, and returns the chain if everything succeeds
+ *
+ * @param objectMapper for serialization
+ * @param keyPair the keypair to generate the csr for
+ * @throws IOException if there is a problem during the process
+ * @returnd the resulting certificate chain
+ */
+ public X509Certificate[] perform(ObjectMapper objectMapper, KeyPair
keyPair) throws IOException {
+ try {
+ List<X509Certificate> certificates = new ArrayList<>();
+
+ HttpClientBuilder httpClientBuilder =
httpClientBuilderSupplier.get();
+ SSLContextBuilder sslContextBuilder =
SSLContextBuilder.create();
+
+ // We will be validating that we are talking to the correct
host once we get the response's hmac of the token and public key of the ca
+ sslContextBuilder.loadTrustMaterial(null, new
TrustSelfSignedStrategy());
+ httpClientBuilder.setSSLSocketFactory(new
TlsCertificateAuthorityClientSocketFactory(sslContextBuilder.build(),
caHostname, certificates));
+
+ String jsonResponseString;
+ int responseCode;
+ try (CloseableHttpClient client = httpClientBuilder.build()) {
+ JcaPKCS10CertificationRequest request =
tlsHelper.generateCertificationRequest(dn, keyPair);
+ TlsCertificateAuthorityRequest
tlsCertificateAuthorityRequest = new
TlsCertificateAuthorityRequest(tlsHelper.calculateHMac(token,
request.getPublicKey()),
+ tlsHelper.pemEncodeJcaObject(request));
+
+ HttpPost httpPost = new HttpPost();
+ httpPost.setEntity(new
ByteArrayEntity(objectMapper.writeValueAsBytes(tlsCertificateAuthorityRequest)));
+
+ try (CloseableHttpResponse response = client.execute(new
HttpHost(caHostname, port, "https"), httpPost)) {
+ jsonResponseString = IOUtils.toString(new
BoundedInputStream(response.getEntity().getContent(), 1024 * 1024),
StandardCharsets.UTF_8);
+ responseCode =
response.getStatusLine().getStatusCode();
+ }
+ }
+
+ if (responseCode != Response.SC_OK) {
+ throw new IOException(RECEIVED_RESPONSE_CODE +
responseCode + " with payload " + jsonResponseString);
--- End diff --
We should be very careful and evaluate all possible responses from the
server to ensure that something sensitive is not accidentally exposed through
an exception being printed in a log if there is an error condition.
> Command Line Keystore and Truststore utility
> --------------------------------------------
>
> Key: NIFI-2193
> URL: https://issues.apache.org/jira/browse/NIFI-2193
> Project: Apache NiFi
> Issue Type: New Feature
> Reporter: Bryan Rosander
> Assignee: Bryan Rosander
>
> In order to facilitate secure setup of NiFi, it would be useful to have a
> command line utility capable of generating the required keystores,
> truststore, and relevant configuration files.
> It should be able to generate keystores for each NiFi node, a truststore that
> they all use, and relevant passwords and configuration files for using the
> keystores and truststore.
> Additionally, in order to support distributed deployment, a web based
> certificate authority with corresponding client will allow for each NiFi
> instance to generate its own keypair and then request signing by the CA.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)