From 83fd4ca291bd8cb95e611511a73894a9318e820a Mon Sep 17 00:00:00 2001 From: Mike Thomsen Date: Fri, 12 Jun 2020 14:49:43 -0400 Subject: [PATCH] NIFI-7526 Updated code to use the new helper library for OkHttp. Signed-off-by: Pierre Villard This closes #4331. --- .../nifi-oauth2-provider-service/pom.xml | 6 + .../nifi/oauth2/OAuth2TokenProviderImpl.java | 46 +++++- .../java/org/apache/nifi/oauth2/Util.java | 139 ------------------ 3 files changed, 44 insertions(+), 147 deletions(-) delete mode 100644 nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/src/main/java/org/apache/nifi/oauth2/Util.java diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/pom.xml b/nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/pom.xml index 14dadf95d9..9c746e21e3 100644 --- a/nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/pom.xml +++ b/nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/pom.xml @@ -94,5 +94,11 @@ jetty-server test + + org.apache.nifi + nifi-web-utils + 1.12.0-SNAPSHOT + compile + diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/src/main/java/org/apache/nifi/oauth2/OAuth2TokenProviderImpl.java b/nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/src/main/java/org/apache/nifi/oauth2/OAuth2TokenProviderImpl.java index dfae289d6f..dd67e040da 100644 --- a/nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/src/main/java/org/apache/nifi/oauth2/OAuth2TokenProviderImpl.java +++ b/nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/src/main/java/org/apache/nifi/oauth2/OAuth2TokenProviderImpl.java @@ -17,6 +17,7 @@ package org.apache.nifi.oauth2; +import com.fasterxml.jackson.databind.ObjectMapper; import okhttp3.FormBody; import okhttp3.OkHttpClient; import okhttp3.Request; @@ -29,6 +30,8 @@ import org.apache.nifi.components.PropertyDescriptor; import org.apache.nifi.controller.AbstractControllerService; import org.apache.nifi.controller.ConfigurationContext; import org.apache.nifi.processor.exception.ProcessException; +import org.apache.nifi.security.util.OkHttpClientUtils; +import org.apache.nifi.security.util.TlsConfiguration; import org.apache.nifi.ssl.SSLContextService; import org.apache.nifi.security.util.SslContextFactory; import org.apache.nifi.util.StringUtils; @@ -36,8 +39,7 @@ import org.apache.nifi.util.StringUtils; import javax.net.ssl.SSLContext; import java.io.IOException; import java.util.List; - -import static org.apache.nifi.oauth2.Util.parseTokenResponse; +import java.util.Map; @Tags({"oauth2", "provider", "authorization" }) @CapabilityDescription("This controller service provides a way of working with access and refresh tokens via the " + @@ -88,12 +90,9 @@ public class OAuth2TokenProviderImpl extends AbstractControllerService implement private OkHttpClient.Builder getClientBuilder() { OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder(); - if (sslContext != null) { - try { - Util.setSslSocketFactory(clientBuilder, sslContextService, sslContext, false); - } catch (Exception e) { - throw new ProcessException(e); - } + if (sslContextService != null) { + final TlsConfiguration tlsConfiguration = sslContextService.createTlsConfiguration(); + OkHttpClientUtils.applyTlsToOkHttpClientBuilder(tlsConfiguration, clientBuilder); } return clientBuilder; @@ -152,4 +151,35 @@ public class OAuth2TokenProviderImpl extends AbstractControllerService implement return executePost(client, newRequest); } + + private static final ObjectMapper MAPPER = new ObjectMapper(); + + public static final String KEY_ACCESS_TOKEN = "access_token"; + public static final String KEY_REFRESH_TOKEN = "refresh_token"; + public static final String KEY_EXPIRES = "expires_in"; + public static final String KEY_TOKEN_TYPE = "token_type"; + public static final String KEY_SCOPE = "scope"; + + public AccessToken parseTokenResponse(String rawResponse) { + try { + Map parsed = MAPPER.readValue(rawResponse, Map.class); + String accessToken = (String)parsed.get(KEY_ACCESS_TOKEN); + String refreshToken = (String)parsed.get(KEY_REFRESH_TOKEN); + Integer expires = (Integer)parsed.get(KEY_EXPIRES); + String tokenType = (String)parsed.get(KEY_TOKEN_TYPE); + String scope = (String)parsed.get(KEY_SCOPE); + + if (StringUtils.isEmpty(accessToken)) { + throw new Exception(String.format("Missing value for %s", KEY_ACCESS_TOKEN)); + } + + if (StringUtils.isEmpty(tokenType)) { + throw new Exception(String.format("Missing value for %s", KEY_TOKEN_TYPE)); + } + + return new AccessToken(accessToken, refreshToken, tokenType, expires, scope); + } catch (Exception ex) { + throw new ProcessException(ex); + } + } } diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/src/main/java/org/apache/nifi/oauth2/Util.java b/nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/src/main/java/org/apache/nifi/oauth2/Util.java deleted file mode 100644 index 9ef003822b..0000000000 --- a/nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/src/main/java/org/apache/nifi/oauth2/Util.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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.oauth2; - -import com.fasterxml.jackson.databind.ObjectMapper; -import okhttp3.OkHttpClient; -import org.apache.nifi.processor.exception.ProcessException; -import org.apache.nifi.ssl.SSLContextService; -import org.apache.nifi.util.StringUtils; - -import javax.net.ssl.KeyManager; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; -import java.io.FileInputStream; -import java.io.IOException; -import java.security.KeyManagementException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.UnrecoverableKeyException; -import java.security.cert.CertificateException; -import java.util.Map; - -public class Util { - private static final ObjectMapper MAPPER = new ObjectMapper(); - - /** - * This code as taken from the InvokeHttp processor from Apache NiFi 1.10-SNAPSHOT found here: - * - * https://github.com/apache/nifi/blob/1cadc722229ad50cf569ee107eaeeb95dc216ea2/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/InvokeHTTP.java - */ - public static void setSslSocketFactory(OkHttpClient.Builder okHttpClientBuilder, SSLContextService sslService, SSLContext sslContext, boolean setAsSocketFactory) - throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException { - - final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509"); - // initialize the KeyManager array to null and we will overwrite later if a keystore is loaded - KeyManager[] keyManagers = null; - - // we will only initialize the keystore if properties have been supplied by the SSLContextService - if (sslService.isKeyStoreConfigured()) { - final String keystoreLocation = sslService.getKeyStoreFile(); - final String keystorePass = sslService.getKeyStorePassword(); - final String keystoreType = sslService.getKeyStoreType(); - - // prepare the keystore - final KeyStore keyStore = KeyStore.getInstance(keystoreType); - - try (FileInputStream keyStoreStream = new FileInputStream(keystoreLocation)) { - keyStore.load(keyStoreStream, keystorePass.toCharArray()); - } - - keyManagerFactory.init(keyStore, keystorePass.toCharArray()); - keyManagers = keyManagerFactory.getKeyManagers(); - } - - // we will only initialize the truststure if properties have been supplied by the SSLContextService - if (sslService.isTrustStoreConfigured()) { - // load truststore - final String truststoreLocation = sslService.getTrustStoreFile(); - final String truststorePass = sslService.getTrustStorePassword(); - final String truststoreType = sslService.getTrustStoreType(); - - KeyStore truststore = KeyStore.getInstance(truststoreType); - truststore.load(new FileInputStream(truststoreLocation), truststorePass.toCharArray()); - trustManagerFactory.init(truststore); - } - - /* - TrustManagerFactory.getTrustManagers returns a trust manager for each type of trust material. Since we are getting a trust manager factory that uses "X509" - as it's trust management algorithm, we are able to grab the first (and thus the most preferred) and use it as our x509 Trust Manager - https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/TrustManagerFactory.html#getTrustManagers-- - */ - final X509TrustManager x509TrustManager; - TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); - if (trustManagers[0] != null) { - x509TrustManager = (X509TrustManager) trustManagers[0]; - } else { - throw new IllegalStateException("List of trust managers is null"); - } - - // if keystore properties were not supplied, the keyManagers array will be null - sslContext.init(keyManagers, trustManagerFactory.getTrustManagers(), null); - - final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); - okHttpClientBuilder.sslSocketFactory(sslSocketFactory, x509TrustManager); - if (setAsSocketFactory) { - okHttpClientBuilder.socketFactory(sslSocketFactory); - } - } - - public static final String KEY_ACCESS_TOKEN = "access_token"; - public static final String KEY_REFRESH_TOKEN = "refresh_token"; - public static final String KEY_EXPIRES = "expires_in"; - public static final String KEY_TOKEN_TYPE = "token_type"; - public static final String KEY_SCOPE = "scope"; - - public static AccessToken parseTokenResponse(String rawResponse) { - try { - Map parsed = MAPPER.readValue(rawResponse, Map.class); - String accessToken = (String)parsed.get(KEY_ACCESS_TOKEN); - String refreshToken = (String)parsed.get(KEY_REFRESH_TOKEN); - Integer expires = (Integer)parsed.get(KEY_EXPIRES); - String tokenType = (String)parsed.get(KEY_TOKEN_TYPE); - String scope = (String)parsed.get(KEY_SCOPE); - - if (StringUtils.isEmpty(accessToken)) { - throw new Exception(String.format("Missing value for %s", KEY_ACCESS_TOKEN)); - } - - if (StringUtils.isEmpty(tokenType)) { - throw new Exception(String.format("Missing value for %s", KEY_TOKEN_TYPE)); - } - - return new AccessToken(accessToken, refreshToken, tokenType, expires, scope); - } catch (Exception ex) { - throw new ProcessException(ex); - } - } -}