/* * 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.web.util; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.config.ClientConfig; import com.sun.jersey.api.client.config.DefaultClientConfig; import com.sun.jersey.api.json.JSONConfiguration; import com.sun.jersey.client.urlconnection.HTTPSProperties; import org.apache.commons.lang3.StringUtils; import org.apache.nifi.security.util.CertificateUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLSession; import java.security.cert.Certificate; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; import java.util.List; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * Common utilities related to web development. * */ public final class WebUtils { private static Logger logger = LoggerFactory.getLogger(WebUtils.class); final static ReadWriteLock lock = new ReentrantReadWriteLock(); private WebUtils() { } /** * Creates a client for non-secure requests. The client will be created * using the given configuration. Additionally, the client will be * automatically configured for JSON serialization/deserialization. * * @param config client configuration * * @return a Client instance */ public static Client createClient(final ClientConfig config) { return createClientHelper(config, null); } /** * Creates a client for secure requests. The client will be created using * the given configuration and security context. Additionally, the client * will be automatically configured for JSON serialization/deserialization. * * @param config client configuration * @param ctx security context * * @return a Client instance */ public static Client createClient(final ClientConfig config, final SSLContext ctx) { return createClientHelper(config, ctx); } /** * A helper method for creating clients. The client will be created using * the given configuration and security context. Additionally, the client * will be automatically configured for JSON serialization/deserialization. * * @param config client configuration * @param ctx security context, which may be null for non-secure client * creation * * @return a Client instance */ private static Client createClientHelper(final ClientConfig config, final SSLContext ctx) { final ClientConfig finalConfig = (config == null) ? new DefaultClientConfig() : config; if (ctx != null && StringUtils.isBlank((String) finalConfig.getProperty(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES))) { // custom hostname verifier that checks subject alternative names against the hostname of the URI final HostnameVerifier hostnameVerifier = new HostnameVerifier() { @Override public boolean verify(final String hostname, final SSLSession ssls) { try { for (final Certificate peerCertificate : ssls.getPeerCertificates()) { if (peerCertificate instanceof X509Certificate) { final X509Certificate x509Cert = (X509Certificate) peerCertificate; final List<String> subjectAltNames = CertificateUtils.getSubjectAlternativeNames(x509Cert); if (subjectAltNames.contains(hostname.toLowerCase())) { return true; } } } } catch (final SSLPeerUnverifiedException | CertificateParsingException ex) { logger.warn("Hostname Verification encountered exception verifying hostname due to: " + ex, ex); } return false; } }; finalConfig.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(hostnameVerifier, ctx)); } finalConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); finalConfig.getClasses().add(ObjectMapperResolver.class); // web client for restful request return Client.create(finalConfig); } }