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

io.dropwizard.jetty.HttpsConnectorFactory Maven / Gradle / Ivy

The newest version!
package io.dropwizard.jetty;

import com.codahale.metrics.MetricRegistry;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import io.dropwizard.validation.ValidationMethod;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
import org.eclipse.jetty.util.thread.Scheduler;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.hibernate.validator.constraints.NotEmpty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import java.io.File;
import java.net.URI;
import java.security.KeyStore;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Builds HTTPS connectors (HTTP over TLS/SSL).
 * 

* Configuration Parameters: *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
NameDefaultDescription
{@code keyStorePath}REQUIRED * The path to the Java key store which contains the host certificate and private key. *
{@code keyStorePassword}REQUIRED * The password used to access the key store. *
{@code keyStoreType}{@code JKS} * The type of key store (usually {@code JKS}, {@code PKCS12}, {@code JCEKS}, * {@code Windows-MY}, or {@code Windows-ROOT}). *
{@code keyStoreProvider}(none) * The JCE provider to use to access the key store. *
{@code trustStorePath}(none) * The path to the Java key store which contains the CA certificates used to establish * trust. *
{@code trustStorePassword}(none)The password used to access the trust store.
{@code trustStoreType}{@code JKS} * The type of trust store (usually {@code JKS}, {@code PKCS12}, {@code JCEKS}, * {@code Windows-MY}, or {@code Windows-ROOT}). *
{@code trustStoreProvider}(none) * The JCE provider to use to access the trust store. *
{@code keyManagerPassword}(none)The password, if any, for the key manager.
{@code needClientAuth}(none)Whether or not client authentication is required.
{@code wantClientAuth}(none)Whether or not client authentication is requested.
{@code certAlias}(none)The alias of the certificate to use.
{@code crlPath}(none)The path to the file which contains the Certificate Revocation List.
{@code enableCRLDP}falseWhether or not CRL Distribution Points (CRLDP) support is enabled.
{@code enableOCSP}falseWhether or not On-Line Certificate Status Protocol (OCSP) support is enabled.
{@code maxCertPathLength}(unlimited)The maximum certification path length.
{@code ocspResponderUrl}(none)The location of the OCSP responder.
{@code jceProvider}(none)The name of the JCE provider to use for cryptographic support.
{@code validateCerts}false * Whether or not to validate TLS certificates before starting. If enabled, Dropwizard * will refuse to start with expired or otherwise invalid certificates. This option will * cause unconditional failure in Dropwizard 1.x until a new validation mechanism can be * implemented. *
{@code validatePeers}false * Whether or not to validate TLS peer certificates. This option will * cause unconditional failure in Dropwizard 1.x until a new validation mechanism can be * implemented. *
{@code supportedProtocols}JVM default * A list of protocols (e.g., {@code SSLv3}, {@code TLSv1}) which are supported. All * other protocols will be refused. *
{@code excludedProtocols}Jetty's default * A list of protocols (e.g., {@code SSLv3}, {@code TLSv1}) which are excluded. These * protocols will be refused. *
{@code supportedCipherSuites}JVM default * A list of cipher suites (e.g., {@code TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256}) which * are supported. All other cipher suites will be refused *
{@code excludedCipherSuites}Jetty's default * A list of cipher suites (e.g., {@code TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256}) which * are excluded. These cipher suites will be refused. *
{@code allowRenegotiation}trueWhether or not TLS renegotiation is allowed.
{@code endpointIdentificationAlgorithm}(none) * Which endpoint identification algorithm, if any, to use during the TLS handshake. *
*

* For more configuration parameters, see {@link HttpConnectorFactory}. * * @see HttpConnectorFactory */ @JsonTypeName("https") public class HttpsConnectorFactory extends HttpConnectorFactory { private static final Logger LOGGER = LoggerFactory.getLogger(HttpsConnectorFactory.class); private static final AtomicBoolean LOGGED = new AtomicBoolean(false); @Nullable private String keyStorePath; @Nullable private String keyStorePassword; @NotEmpty private String keyStoreType = "JKS"; @Nullable private String keyStoreProvider; @Nullable private String trustStorePath; @Nullable private String trustStorePassword; @NotEmpty private String trustStoreType = "JKS"; @Nullable private String trustStoreProvider; @Nullable private String keyManagerPassword; @Nullable private Boolean needClientAuth; @Nullable private Boolean wantClientAuth; @Nullable private String certAlias; @Nullable private File crlPath; @Nullable private Boolean enableCRLDP; @Nullable private Boolean enableOCSP; @Nullable private Integer maxCertPathLength; @Nullable private URI ocspResponderUrl; @Nullable private String jceProvider; private boolean validateCerts = false; private boolean validatePeers = false; @Nullable private List supportedProtocols; @Nullable private List excludedProtocols; @Nullable private List supportedCipherSuites; @Nullable private List excludedCipherSuites; private boolean allowRenegotiation = true; @Nullable private String endpointIdentificationAlgorithm; @JsonProperty public boolean getAllowRenegotiation() { return allowRenegotiation; } @JsonProperty public void setAllowRenegotiation(boolean allowRenegotiation) { this.allowRenegotiation = allowRenegotiation; } @JsonProperty @Nullable public String getEndpointIdentificationAlgorithm() { return endpointIdentificationAlgorithm; } @JsonProperty public void setEndpointIdentificationAlgorithm(String endpointIdentificationAlgorithm) { this.endpointIdentificationAlgorithm = endpointIdentificationAlgorithm; } @JsonProperty @Nullable public String getKeyStorePath() { return keyStorePath; } @JsonProperty public void setKeyStorePath(String keyStorePath) { this.keyStorePath = keyStorePath; } @JsonProperty @Nullable public String getKeyStorePassword() { return keyStorePassword; } @JsonProperty public void setKeyStorePassword(String keyStorePassword) { this.keyStorePassword = keyStorePassword; } @JsonProperty public String getKeyStoreType() { return keyStoreType; } @JsonProperty public void setKeyStoreType(String keyStoreType) { this.keyStoreType = keyStoreType; } @JsonProperty @Nullable public String getKeyStoreProvider() { return keyStoreProvider; } @JsonProperty public void setKeyStoreProvider(String keyStoreProvider) { this.keyStoreProvider = keyStoreProvider; } @JsonProperty public String getTrustStoreType() { return trustStoreType; } @JsonProperty public void setTrustStoreType(String trustStoreType) { this.trustStoreType = trustStoreType; } @JsonProperty @Nullable public String getTrustStoreProvider() { return trustStoreProvider; } @JsonProperty public void setTrustStoreProvider(String trustStoreProvider) { this.trustStoreProvider = trustStoreProvider; } @JsonProperty @Nullable public String getKeyManagerPassword() { return keyManagerPassword; } @JsonProperty public void setKeyManagerPassword(String keyManagerPassword) { this.keyManagerPassword = keyManagerPassword; } @JsonProperty @Nullable public String getTrustStorePath() { return trustStorePath; } @JsonProperty public void setTrustStorePath(String trustStorePath) { this.trustStorePath = trustStorePath; } @JsonProperty @Nullable public String getTrustStorePassword() { return trustStorePassword; } @JsonProperty public void setTrustStorePassword(@Nullable String trustStorePassword) { this.trustStorePassword = trustStorePassword; } @JsonProperty @Nullable public Boolean getNeedClientAuth() { return needClientAuth; } @JsonProperty public void setNeedClientAuth(Boolean needClientAuth) { this.needClientAuth = needClientAuth; } @JsonProperty @Nullable public Boolean getWantClientAuth() { return wantClientAuth; } @JsonProperty public void setWantClientAuth(Boolean wantClientAuth) { this.wantClientAuth = wantClientAuth; } @JsonProperty @Nullable public String getCertAlias() { return certAlias; } @JsonProperty public void setCertAlias(String certAlias) { this.certAlias = certAlias; } @JsonProperty @Nullable public File getCrlPath() { return crlPath; } @JsonProperty public void setCrlPath(File crlPath) { this.crlPath = crlPath; } @JsonProperty @Nullable public Boolean getEnableCRLDP() { return enableCRLDP; } @JsonProperty public void setEnableCRLDP(Boolean enableCRLDP) { this.enableCRLDP = enableCRLDP; } @JsonProperty @Nullable public Boolean getEnableOCSP() { return enableOCSP; } @JsonProperty public void setEnableOCSP(Boolean enableOCSP) { this.enableOCSP = enableOCSP; } @JsonProperty @Nullable public Integer getMaxCertPathLength() { return maxCertPathLength; } @JsonProperty public void setMaxCertPathLength(Integer maxCertPathLength) { this.maxCertPathLength = maxCertPathLength; } @JsonProperty @Nullable public URI getOcspResponderUrl() { return ocspResponderUrl; } @JsonProperty public void setOcspResponderUrl(URI ocspResponderUrl) { this.ocspResponderUrl = ocspResponderUrl; } @JsonProperty @Nullable public String getJceProvider() { return jceProvider; } @JsonProperty public void setJceProvider(String jceProvider) { this.jceProvider = jceProvider; } @JsonProperty public boolean getValidatePeers() { return validatePeers; } @JsonProperty public void setValidatePeers(boolean validatePeers) { this.validatePeers = validatePeers; } @JsonProperty @Nullable public List getSupportedProtocols() { return supportedProtocols; } @JsonProperty public void setSupportedProtocols(List supportedProtocols) { this.supportedProtocols = supportedProtocols; } @JsonProperty @Nullable public List getExcludedProtocols() { return excludedProtocols; } @JsonProperty public void setExcludedProtocols(List excludedProtocols) { this.excludedProtocols = excludedProtocols; } @JsonProperty @Nullable public List getSupportedCipherSuites() { return supportedCipherSuites; } @JsonProperty @Nullable public List getExcludedCipherSuites() { return excludedCipherSuites; } @JsonProperty public void setExcludedCipherSuites(List excludedCipherSuites) { this.excludedCipherSuites = excludedCipherSuites; } @JsonProperty public void setSupportedCipherSuites(List supportedCipherSuites) { this.supportedCipherSuites = supportedCipherSuites; } @JsonProperty public boolean isValidateCerts() { return validateCerts; } @JsonProperty public void setValidateCerts(boolean validateCerts) { this.validateCerts = validateCerts; } @ValidationMethod(message = "keyStorePath should not be null") public boolean isValidKeyStorePath() { return keyStoreType.startsWith("Windows-") || keyStorePath != null; } @ValidationMethod(message = "keyStorePassword should not be null or empty") public boolean isValidKeyStorePassword() { return keyStoreType.startsWith("Windows-") || !Strings.isNullOrEmpty(keyStorePassword); } @Override public Connector build(Server server, MetricRegistry metrics, String name, @Nullable ThreadPool threadPool) { final HttpConfiguration httpConfig = buildHttpConfiguration(); final HttpConnectionFactory httpConnectionFactory = buildHttpConnectionFactory(httpConfig); final SslContextFactory sslContextFactory = configureSslContextFactory(new SslContextFactory()); sslContextFactory.addLifeCycleListener(logSslInfoOnStart(sslContextFactory)); server.addBean(sslContextFactory); server.addBean(new SslReload(sslContextFactory, this::configureSslContextFactory)); final SslConnectionFactory sslConnectionFactory = new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.toString()); final Scheduler scheduler = new ScheduledExecutorScheduler(); final ByteBufferPool bufferPool = buildBufferPool(); return buildConnector(server, scheduler, bufferPool, name, threadPool, new Jetty93InstrumentedConnectionFactory( sslConnectionFactory, metrics.timer(httpConnections())), httpConnectionFactory); } @Override protected HttpConfiguration buildHttpConfiguration() { final HttpConfiguration config = super.buildHttpConfiguration(); config.setSecureScheme("https"); config.setSecurePort(getPort()); config.addCustomizer(new SecureRequestCustomizer()); return config; } /** Register a listener that waits until the ssl context factory has started. Once it has * started we can grab the fully initialized context so we can log the parameters. */ protected AbstractLifeCycle.AbstractLifeCycleListener logSslInfoOnStart(final SslContextFactory sslContextFactory) { return new AbstractLifeCycle.AbstractLifeCycleListener() { @Override public void lifeCycleStarted(LifeCycle event) { logSupportedParameters(sslContextFactory.getSslContext()); } }; } private void logSupportedParameters(SSLContext context) { if (LOGGED.compareAndSet(false, true)) { final String[] protocols = context.getSupportedSSLParameters().getProtocols(); final SSLSocketFactory factory = context.getSocketFactory(); final String[] cipherSuites = factory.getSupportedCipherSuites(); LOGGER.info("Supported protocols: {}", Arrays.toString(protocols)); LOGGER.info("Supported cipher suites: {}", Arrays.toString(cipherSuites)); if (getSupportedProtocols() != null) { LOGGER.info("Configured protocols: {}", getSupportedProtocols()); } if (getExcludedProtocols() != null) { LOGGER.info("Excluded protocols: {}", getExcludedProtocols()); } if (getSupportedCipherSuites() != null) { LOGGER.info("Configured cipher suites: {}", getSupportedCipherSuites()); } if (getExcludedCipherSuites() != null) { LOGGER.info("Excluded cipher suites: {}", getExcludedCipherSuites()); } } } protected SslContextFactory configureSslContextFactory(SslContextFactory factory) { if (keyStorePath != null) { factory.setKeyStorePath(keyStorePath); } final String keyStoreType = getKeyStoreType(); if (keyStoreType.startsWith("Windows-")) { try { final KeyStore keyStore = KeyStore.getInstance(keyStoreType); keyStore.load(null, null); factory.setKeyStore(keyStore); } catch (Exception e) { throw new IllegalStateException("Windows key store not supported", e); } } else { factory.setKeyStoreType(keyStoreType); factory.setKeyStorePassword(keyStorePassword); } if (keyStoreProvider != null) { factory.setKeyStoreProvider(keyStoreProvider); } final String trustStoreType = getTrustStoreType(); if (trustStoreType.startsWith("Windows-")) { try { final KeyStore keyStore = KeyStore.getInstance(trustStoreType); keyStore.load(null, null); factory.setTrustStore(keyStore); } catch (Exception e) { throw new IllegalStateException("Windows key store not supported", e); } } else { if (trustStorePath != null) { factory.setTrustStorePath(trustStorePath); } if (trustStorePassword != null) { factory.setTrustStorePassword(trustStorePassword); } factory.setTrustStoreType(trustStoreType); } if (trustStoreProvider != null) { factory.setTrustStoreProvider(trustStoreProvider); } if (keyManagerPassword != null) { factory.setKeyManagerPassword(keyManagerPassword); } if (needClientAuth != null) { factory.setNeedClientAuth(needClientAuth); } if (wantClientAuth != null) { factory.setWantClientAuth(wantClientAuth); } if (certAlias != null) { factory.setCertAlias(certAlias); } if (crlPath != null) { factory.setCrlPath(crlPath.getAbsolutePath()); } if (enableCRLDP != null) { factory.setEnableCRLDP(enableCRLDP); } if (enableOCSP != null) { factory.setEnableOCSP(enableOCSP); } if (maxCertPathLength != null) { factory.setMaxCertPathLength(maxCertPathLength); } if (ocspResponderUrl != null) { factory.setOcspResponderURL(ocspResponderUrl.toASCIIString()); } if (jceProvider != null) { factory.setProvider(jceProvider); } factory.setRenegotiationAllowed(allowRenegotiation); factory.setEndpointIdentificationAlgorithm(endpointIdentificationAlgorithm); factory.setValidateCerts(validateCerts); factory.setValidatePeerCerts(validatePeers); if (supportedProtocols != null) { factory.setIncludeProtocols(Iterables.toArray(supportedProtocols, String.class)); } if (excludedProtocols != null) { factory.setExcludeProtocols(Iterables.toArray(excludedProtocols, String.class)); } if (supportedCipherSuites != null) { factory.setIncludeCipherSuites(Iterables.toArray(supportedCipherSuites, String.class)); } if (excludedCipherSuites != null) { factory.setExcludeCipherSuites(Iterables.toArray(excludedCipherSuites, String.class)); } return factory; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy