All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.navercorp.pinpoint.grpc.security.SslContextFactory Maven / Gradle / Ivy

There is a newer version: 3.0.0
Show newest version
/*
 * Copyright 2021 NAVER Corp.
 *
 * Licensed 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 com.navercorp.pinpoint.grpc.security;

import com.navercorp.pinpoint.common.util.CollectionUtils;
import com.navercorp.pinpoint.common.util.StringUtils;
import com.navercorp.pinpoint.grpc.util.Resource;

import io.grpc.netty.GrpcSslContexts;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;
import io.netty.handler.ssl.SupportedCipherSuiteFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLException;
import javax.net.ssl.TrustManagerFactory;
import java.security.KeyStore;
import java.util.List;
import java.util.Objects;

/**
 * @author Taejin Koo
 */
public final class SslContextFactory {

    private static final Logger LOGGER = LoggerFactory.getLogger(SslContextFactory.class);

    public static SslContext create(SslServerConfig serverConfig) throws SSLException {
        Objects.requireNonNull(serverConfig, "serverConfig");

        SslProvider sslProvider = getSslProvider(serverConfig.getSslProviderType());

        SslContextBuilder sslContextBuilder;
        try {
            Resource keyCertChainFileResource = serverConfig.getKeyCertChainResource();
            Resource keyResource = serverConfig.getKeyResource();

            sslContextBuilder = SslContextBuilder.forServer(keyCertChainFileResource.getInputStream(), keyResource.getInputStream());
            SslContext sslContext = createSslContext(sslContextBuilder, sslProvider);

            assertValidCipherSuite(sslContext);

            return sslContext;
        } catch (SSLException e) {
            throw e;
        } catch (Exception e) {
            throw new SSLException(e);
        }
    }

    public static SslContext create(SslClientConfig clientConfig) throws SSLException {
        Objects.requireNonNull(clientConfig, "clientConfig");

        if (!clientConfig.isEnable()) {
            throw new IllegalArgumentException("sslConfig is disabled.");
        }

        SslProvider sslProvider = getSslProvider(clientConfig.getSslProviderType());

        SslContextBuilder sslContextBuilder = null;
        try {
            sslContextBuilder = SslContextBuilder.forClient();

            Resource trustCertResource = clientConfig.getTrustCertResource();
            if (trustCertResource != null) {
                sslContextBuilder.trustManager(trustCertResource.getInputStream());
            } else {
                // Loads default Root CA certificates (generally, from JAVA_HOME/lib/cacerts)
                TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                trustManagerFactory.init((KeyStore)null);
                sslContextBuilder.trustManager(trustManagerFactory);
            }

            SslContext sslContext = createSslContext(sslContextBuilder, sslProvider);

            assertValidCipherSuite(sslContext);

            return sslContext;
        } catch (SSLException e) {
            throw e;
        } catch (Exception e) {
            throw new SSLException(e);
        }
    }

    private static SslContext createSslContext(SslContextBuilder sslContextBuilder, SslProvider sslProvider) throws SSLException {
        sslContextBuilder.sslProvider(sslProvider);

        sslContextBuilder.protocols(SecurityConstants.DEFAULT_SUPPORT_PROTOCOLS.toArray(new String[0]));
        sslContextBuilder.ciphers(SecurityConstants.DEFAULT_SUPPORT_CIPHER_SUITE, SupportedCipherSuiteFilter.INSTANCE);

        SslContextBuilder configure = GrpcSslContexts.configure(sslContextBuilder, sslProvider);
        return configure.build();
    }

    private static void assertValidCipherSuite(SslContext sslContext) throws SSLException {
        Objects.requireNonNull(sslContext, "sslContext must not be null");

        List supportedCipherSuiteList = sslContext.cipherSuites();
        if (CollectionUtils.isEmpty(supportedCipherSuiteList)) {
            throw new SSLException("cipherSuites must not be empty");
        }

        for (String cipherSuite : supportedCipherSuiteList) {
            if (SecurityConstants.BAD_CIPHER_SUITE_LIST.contains(cipherSuite)) {
                throw new SSLException(cipherSuite + " is not safe. Please check this url.(https://httpwg.org/specs/rfc7540.html#BadCipherSuites)");
            }
        }

        LOGGER.info("Support cipher list : {} {}", sslContext, supportedCipherSuiteList);
    }

    static SslProvider getSslProvider(String providerType) throws SSLException {
        if (StringUtils.isEmpty(providerType)) {
            return SslProvider.OPENSSL;
        }

        if (SslProvider.OPENSSL.name().equalsIgnoreCase(providerType)) {
            return SslProvider.OPENSSL;
        }

        if (SslProvider.JDK.name().equalsIgnoreCase(providerType)) {
            return SslProvider.JDK;
        }

        throw new SSLException("can't find SslProvider. value:" + providerType);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy