You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwebbeans.apache.org by rm...@apache.org on 2018/07/06 08:33:28 UTC
svn commit: r1835215 - in /openwebbeans/meecrowave/trunk: ./
meecrowave-arquillian/ meecrowave-core/ meecrowave-doc/
meecrowave-gradle-plugin/ meecrowave-jolokia/ meecrowave-jpa/
meecrowave-jta/ meecrowave-letsencrypt/ meecrowave-letsencrypt/src/ meecr...
Author: rmannibucau
Date: Fri Jul 6 08:33:27 2018
New Revision: 1835215
URL: http://svn.apache.org/viewvc?rev=1835215&view=rev
Log:
MEECROWAVE-125 add Automatic-Module-Name in jars
Added:
openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/
openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/pom.xml
openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/
openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/
openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/java/
openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/java/org/
openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/java/org/apache/
openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/java/org/apache/meecrowave/
openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/java/org/apache/meecrowave/letencrypt/
openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/java/org/apache/meecrowave/letencrypt/LetsEncryptReloadLifecycle.java
openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/java/org/apache/meecrowave/letencrypt/LetsEncryptSetup.java
openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/java/org/apache/meecrowave/letencrypt/LetsEncryptValve.java
openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/resources/
openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/resources/META-INF/
openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/resources/META-INF/services/
openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/resources/META-INF/services/org.apache.meecrowave.runner.Cli$Options
openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/test/
openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/test/java/
Modified:
openwebbeans/meecrowave/trunk/meecrowave-arquillian/pom.xml
openwebbeans/meecrowave/trunk/meecrowave-core/pom.xml
openwebbeans/meecrowave/trunk/meecrowave-doc/pom.xml
openwebbeans/meecrowave/trunk/meecrowave-gradle-plugin/pom.xml
openwebbeans/meecrowave/trunk/meecrowave-jolokia/pom.xml
openwebbeans/meecrowave/trunk/meecrowave-jpa/pom.xml
openwebbeans/meecrowave/trunk/meecrowave-jta/pom.xml
openwebbeans/meecrowave/trunk/meecrowave-maven-plugin/pom.xml
openwebbeans/meecrowave/trunk/meecrowave-oauth2/pom.xml
openwebbeans/meecrowave/trunk/meecrowave-specs-api/pom.xml
openwebbeans/meecrowave/trunk/pom.xml
Modified: openwebbeans/meecrowave/trunk/meecrowave-arquillian/pom.xml
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-arquillian/pom.xml?rev=1835215&r1=1835214&r2=1835215&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-arquillian/pom.xml (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-arquillian/pom.xml Fri Jul 6 08:33:27 2018
@@ -30,6 +30,7 @@
<properties>
<arquillian.version>1.1.13.Final</arquillian.version>
+ <meecrowave.build.name>${project.groupId}.arquillian</meecrowave.build.name>
</properties>
<dependencies>
Modified: openwebbeans/meecrowave/trunk/meecrowave-core/pom.xml
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/pom.xml?rev=1835215&r1=1835214&r2=1835215&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-core/pom.xml (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-core/pom.xml Fri Jul 6 08:33:27 2018
@@ -28,6 +28,10 @@
<artifactId>meecrowave-core</artifactId>
<name>Meecrowave :: Core</name>
+ <properties>
+ <meecrowave.build.name>${project.groupId}.core</meecrowave.build.name>
+ </properties>
+
<dependencies>
<dependency>
<groupId>org.apache.meecrowave</groupId>
Modified: openwebbeans/meecrowave/trunk/meecrowave-doc/pom.xml
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-doc/pom.xml?rev=1835215&r1=1835214&r2=1835215&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-doc/pom.xml (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-doc/pom.xml Fri Jul 6 08:33:27 2018
@@ -32,6 +32,7 @@
<properties>
<jbake.http>false</jbake.http>
<jbake.pdf>true</jbake.pdf>
+ <meecrowave.build.name>${project.groupId}.documentation</meecrowave.build.name>
</properties>
<dependencies>
Modified: openwebbeans/meecrowave/trunk/meecrowave-gradle-plugin/pom.xml
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-gradle-plugin/pom.xml?rev=1835215&r1=1835214&r2=1835215&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-gradle-plugin/pom.xml (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-gradle-plugin/pom.xml Fri Jul 6 08:33:27 2018
@@ -30,6 +30,7 @@
<properties>
<gradle.version>3.1</gradle.version>
+ <meecrowave.build.name>${project.groupId}.gradle</meecrowave.build.name>
</properties>
<dependencies>
Modified: openwebbeans/meecrowave/trunk/meecrowave-jolokia/pom.xml
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-jolokia/pom.xml?rev=1835215&r1=1835214&r2=1835215&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-jolokia/pom.xml (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-jolokia/pom.xml Fri Jul 6 08:33:27 2018
@@ -30,6 +30,7 @@
<properties>
<jolokia.version>2.0.0-M3</jolokia.version>
+ <meecrowave.build.name>${project.groupId}.jolokia</meecrowave.build.name>
</properties>
<dependencies>
Modified: openwebbeans/meecrowave/trunk/meecrowave-jpa/pom.xml
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-jpa/pom.xml?rev=1835215&r1=1835214&r2=1835215&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-jpa/pom.xml (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-jpa/pom.xml Fri Jul 6 08:33:27 2018
@@ -28,6 +28,10 @@
<artifactId>meecrowave-jpa</artifactId>
<name>Meecrowave :: JPA</name>
+ <properties>
+ <meecrowave.build.name>${project.groupId}.jpa</meecrowave.build.name>
+ </properties>
+
<dependencies>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
Modified: openwebbeans/meecrowave/trunk/meecrowave-jta/pom.xml
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-jta/pom.xml?rev=1835215&r1=1835214&r2=1835215&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-jta/pom.xml (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-jta/pom.xml Fri Jul 6 08:33:27 2018
@@ -28,6 +28,10 @@
<artifactId>meecrowave-jta</artifactId>
<name>Meecrowave :: JTA</name>
+ <properties>
+ <meecrowave.build.name>${project.groupId}.jta</meecrowave.build.name>
+ </properties>
+
<dependencies>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
Added: openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/pom.xml
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/pom.xml?rev=1835215&view=auto
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/pom.xml (added)
+++ openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/pom.xml Fri Jul 6 08:33:27 2018
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>meecrowave</artifactId>
+ <groupId>org.apache.meecrowave</groupId>
+ <version>1.2.2-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>meecrowave-letsencrypt</artifactId>
+ <name>Meecrowave :: Let's Encrypt</name>
+
+ <properties>
+ <acme4j.version>2.1</acme4j.version>
+ <meecrowave.build.name>${project.groupId}.letsencrypt</meecrowave.build.name>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.meecrowave</groupId>
+ <artifactId>meecrowave-core</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomcat</groupId>
+ <artifactId>tomcat-catalina</artifactId>
+ <version>${tomcat.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- todo: replace by jaxrs 2 client + jsonb -->
+ <dependency>
+ <groupId>org.shredzone.acme4j</groupId>
+ <artifactId>acme4j-client</artifactId>
+ <version>${acme4j.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.shredzone.acme4j</groupId>
+ <artifactId>acme4j-utils</artifactId>
+ <version>${acme4j.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+</project>
Added: openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/java/org/apache/meecrowave/letencrypt/LetsEncryptReloadLifecycle.java
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/java/org/apache/meecrowave/letencrypt/LetsEncryptReloadLifecycle.java?rev=1835215&view=auto
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/java/org/apache/meecrowave/letencrypt/LetsEncryptReloadLifecycle.java (added)
+++ openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/java/org/apache/meecrowave/letencrypt/LetsEncryptReloadLifecycle.java Fri Jul 6 08:33:27 2018
@@ -0,0 +1,357 @@
+/*
+ * 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.meecrowave.letencrypt;
+
+import static java.util.Optional.ofNullable;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.util.Objects;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BiConsumer;
+import java.util.stream.Stream;
+
+import org.apache.coyote.http11.AbstractHttp11Protocol;
+import org.apache.meecrowave.logging.tomcat.LogFacade;
+import org.apache.meecrowave.runner.Cli;
+import org.apache.meecrowave.runner.cli.CliOption;
+import org.bouncycastle.openssl.PEMKeyPair;
+import org.bouncycastle.openssl.PEMParser;
+import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
+import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
+import org.shredzone.acme4j.Account;
+import org.shredzone.acme4j.AccountBuilder;
+import org.shredzone.acme4j.Authorization;
+import org.shredzone.acme4j.Certificate;
+import org.shredzone.acme4j.Order;
+import org.shredzone.acme4j.Session;
+import org.shredzone.acme4j.Status;
+import org.shredzone.acme4j.challenge.Challenge;
+import org.shredzone.acme4j.challenge.Http01Challenge;
+import org.shredzone.acme4j.exception.AcmeException;
+import org.shredzone.acme4j.util.CSRBuilder;
+
+// we depend on bouncycastle but user myst add it to be able to use that
+// todo: check we can get rid of it and use jaxrs client instead of acme lib
+public class LetsEncryptReloadLifecycle implements AutoCloseable, Runnable {
+
+ private final AtomicReference<LogFacade> logger = new AtomicReference<>();
+
+ private final AbstractHttp11Protocol<?> protocol;
+
+ private final ScheduledExecutorService thread;
+
+ private final ScheduledFuture<?> refreshTask;
+
+ private final LetsEncryptConfig config;
+
+ private final BiConsumer<String, String> challengeUpdater;
+
+ public LetsEncryptReloadLifecycle(final LetsEncryptConfig config, final AbstractHttp11Protocol<?> protocol,
+ final BiConsumer<String, String> challengeUpdater) {
+ this.config = config;
+ this.config.init();
+ this.protocol = protocol;
+ this.challengeUpdater = challengeUpdater;
+
+ final SecurityManager s = System.getSecurityManager();
+ final ThreadGroup group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
+ this.thread = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
+
+ @Override
+ public Thread newThread(final Runnable r) {
+ final Thread newThread = new Thread(group, r, LetsEncryptReloadLifecycle.class.getName() + "_" + hashCode());
+ newThread.setDaemon(false);
+ newThread.setPriority(Thread.NORM_PRIORITY);
+ newThread.setContextClassLoader(getClass().getClassLoader());
+ return newThread;
+ }
+ });
+ refreshTask = this.thread.scheduleAtFixedRate(this, 0L, config.getRefreshInterval(), TimeUnit.SECONDS);
+ }
+
+ @Override
+ public synchronized void run() {
+ final KeyPair userKeyPair = loadOrCreateKeyPair(config.getUserKeySize(), config.getUserKeyLocation());
+ final KeyPair domainKeyPair = loadOrCreateKeyPair(config.getDomainKeySize(), config.getDomainKey());
+
+ final Session session = new Session(config.getEndpoint());
+ try {
+ final Account account = new AccountBuilder().agreeToTermsOfService().useKeyPair(userKeyPair).create(session);
+ final Order order = account.newOrder().domains(config.getDomains().trim().split(",")).create();
+ final boolean updated = order.getAuthorizations().stream().map(authorization -> {
+ try {
+ return authorize(authorization);
+ } catch (final AcmeException e) {
+ getLogger().error(e.getMessage(), e);
+ return false;
+ }
+ }).reduce(false, (previous, val) -> previous || val);
+ if (!updated) {
+ return;
+ }
+
+ final CSRBuilder csrBuilder = new CSRBuilder();
+ csrBuilder.addDomains(config.getDomains());
+ csrBuilder.sign(domainKeyPair);
+
+ try (final Writer writer = new BufferedWriter(new FileWriter(config.getDomainCertificate()))) {
+ csrBuilder.write(writer);
+ }
+
+ order.execute(csrBuilder.getEncoded());
+
+ try {
+ int attempts = config.getRetryCount();
+ while (order.getStatus() != Status.VALID && attempts-- > 0) {
+ if (order.getStatus() == Status.INVALID) {
+ throw new AcmeException("Order failed... Giving up.");
+ }
+ Thread.sleep(config.getRetryTimeoutMs());
+ order.update();
+ }
+ } catch (final InterruptedException ex) {
+ getLogger().error(ex.getMessage());
+ Thread.currentThread().interrupt();
+ return;
+ }
+
+ final Certificate certificate = order.getCertificate();
+ getLogger().info("Got new certificate " + certificate.getLocation() + " for domain(s) " + config.getDomains());
+
+ try (final Writer writer = new BufferedWriter(new FileWriter(config.getDomainChain()))) {
+ certificate.writeCertificate(writer);
+ }
+
+ protocol.reloadSsslHostConfigs();
+ } catch (final AcmeException | IOException ex) {
+ getLogger().error(ex.getMessage(), ex);
+ }
+ }
+
+ private LogFacade getLogger() {
+ LogFacade logFacade = logger.get();
+ if (logFacade == null) {
+ logFacade = new LogFacade(getClass().getName());
+ // ok to use 2 instances since the backing instance will be the same, so ignore returned value
+ logger.compareAndSet(null, logFacade);
+ }
+ return logFacade;
+ }
+
+ @Override
+ public void close() {
+ ofNullable(refreshTask).ifPresent(t -> t.cancel(true));
+ ofNullable(thread).ifPresent(ExecutorService::shutdownNow);
+ try {
+ thread.awaitTermination(5, TimeUnit.SECONDS);
+ } catch (final InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ private boolean authorize(final Authorization authorization) throws AcmeException {
+ final Challenge challenge = httpChallenge(authorization);
+ if (challenge == null) {
+ throw new AcmeException("HTTP challenge is null");
+ }
+ if (challenge.getStatus() == Status.VALID) {
+ return false;
+ }
+
+ challenge.trigger();
+
+ try {
+ int attempts = config.getRetryCount();
+ while (challenge.getStatus() != Status.VALID && attempts-- > 0) {
+ if (challenge.getStatus() == Status.INVALID) {
+ throw new AcmeException("Invalid challenge status, exiting refresh iteration");
+ }
+
+ Thread.sleep(config.getRetryTimeoutMs());
+ challenge.update();
+ }
+ } catch (final InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ }
+
+ if (challenge.getStatus() != Status.VALID) {
+ throw new AcmeException("Challenge for domain " + authorization.getDomain() + ", is invalid, exiting iteration");
+ }
+ return true;
+ }
+
+ private Challenge httpChallenge(final Authorization auth) throws AcmeException {
+ final Http01Challenge challenge = auth.findChallenge(Http01Challenge.TYPE);
+ if (challenge == null) {
+ throw new AcmeException("Challenge is null");
+ }
+
+ challengeUpdater.accept("/.well-known/acme-challenge/" + challenge.getToken(), challenge.getAuthorization());
+ return challenge;
+ }
+
+ private KeyPair loadOrCreateKeyPair(final int keySize, final File file) {
+ if (file.exists()) {
+ try (final PEMParser parser = new PEMParser(new FileReader(file))) {
+ return new JcaPEMKeyConverter().getKeyPair(PEMKeyPair.class.cast(parser.readObject()));
+ } catch (final IOException ex) {
+ throw new IllegalStateException("Can't read PEM file: " + file, ex);
+ }
+ } else {
+ try {
+ final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
+ keyGen.initialize(keySize);
+ final KeyPair keyPair = keyGen.generateKeyPair();
+ try (final JcaPEMWriter writer = new JcaPEMWriter(new FileWriter(file))) {
+ writer.writeObject(keyPair);
+ } catch (final IOException ex) {
+ throw new IllegalStateException("Can't read PEM file: " + file, ex);
+ }
+ return keyPair;
+ } catch (final NoSuchAlgorithmException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+ }
+
+ public static class LetsEncryptConfig implements Cli.Options {
+
+ @CliOption(name = "letsencrypt-refresh-interval", description = "Number of second between let'sencrypt refreshes")
+ private long refreshInterval = 60;
+
+ @CliOption(name = "letsencrypt-domains", description = "Comma separated list of domains to manage")
+ private String domains;
+
+ @CliOption(name = "letsencrypt-key-user-location", description = "Where the user key must be stored")
+ private File userKeyLocation;
+
+ @CliOption(name = "letsencrypt-key-user-size", description = "User key size")
+ private int userKeySize = 2048;
+
+ @CliOption(name = "letsencrypt-key-domain-location", description = "Where the domain key must be stored")
+ private File domainKey;
+
+ @CliOption(name = "letsencrypt-key-domain-size", description = "Domain key size")
+ private int domainKeySize = 2048;
+
+ @CliOption(name = "letsencrypt-certificate-domain-location", description = "Where the domain certificate must be stored")
+ private File domainCertificate;
+
+ @CliOption(name = "letsencrypt-chain-domain-location", description = "Where the domain chain must be stored")
+ private File domainChain;
+
+ @CliOption(name = "letsencrypt-endpoint", description = "Endpoint to use to get the certificates")
+ private String endpoint;
+
+ @CliOption(name = "letsencrypt-endpoint-staging", description = "Ignore if endpoint is set, otherwise it set the endpoint accordingly")
+ private boolean staging = false;
+
+ @CliOption(name = "letsencrypt-retry-timeout-ms", description = "How long to wait before retrying to get the certificate, default is 3s")
+ private long retryTimeoutMs = 3000;
+
+ @CliOption(name = "letsencrypt-retry-count", description = "How many retries to do")
+ private int retryCount = 20;
+
+ public void init() {
+ if (userKeyLocation == null) {
+ userKeyLocation = new File(System.getProperty("catalina.base"), "conf/letsencrypt/user.key");
+ }
+ if (domainKey == null) {
+ domainKey = new File(System.getProperty("catalina.base"), "conf/letsencrypt/domain.key");
+ }
+ if (domainCertificate == null) {
+ domainCertificate = new File(System.getProperty("catalina.base"), "conf/letsencrypt/domain.csr");
+ }
+ if (domainChain == null) {
+ domainChain = new File(System.getProperty("catalina.base"), "conf/letsencrypt/domain.chain.csr");
+ }
+ if (endpoint == null) {
+ if (isStaging()) {
+ endpoint = "https://acme-staging-v02.api.letsencrypt.org/directory";
+ } else {
+ endpoint = "https://acme-v02.api.letsencrypt.org/directory";
+ }
+ }
+ Stream.of(userKeyLocation, domainKey, domainCertificate, domainChain).map(File::getAbsoluteFile)
+ .map(File::getParentFile).filter(Objects::nonNull).distinct().forEach(File::mkdirs);
+ }
+
+ public boolean isStaging() {
+ return staging;
+ }
+
+ public int getRetryCount() {
+ return retryCount;
+ }
+
+ public int getDomainKeySize() {
+ return domainKeySize;
+ }
+
+ public String getEndpoint() {
+ return endpoint;
+ }
+
+ public long getRefreshInterval() {
+ return refreshInterval;
+ }
+
+ public String getDomains() {
+ return domains;
+ }
+
+ public File getUserKeyLocation() {
+ return userKeyLocation;
+ }
+
+ public int getUserKeySize() {
+ return userKeySize;
+ }
+
+ public File getDomainKey() {
+ return domainKey;
+ }
+
+ public File getDomainCertificate() {
+ return domainCertificate;
+ }
+
+ public File getDomainChain() {
+ return domainChain;
+ }
+
+ public long getRetryTimeoutMs() {
+ return retryTimeoutMs;
+ }
+ }
+}
Added: openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/java/org/apache/meecrowave/letencrypt/LetsEncryptSetup.java
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/java/org/apache/meecrowave/letencrypt/LetsEncryptSetup.java?rev=1835215&view=auto
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/java/org/apache/meecrowave/letencrypt/LetsEncryptSetup.java (added)
+++ openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/java/org/apache/meecrowave/letencrypt/LetsEncryptSetup.java Fri Jul 6 08:33:27 2018
@@ -0,0 +1,51 @@
+/*
+ * 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.meecrowave.letencrypt;
+
+import org.apache.catalina.startup.Tomcat;
+import org.apache.coyote.ProtocolHandler;
+import org.apache.coyote.http11.AbstractHttp11Protocol;
+import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.logging.tomcat.LogFacade;
+
+public class LetsEncryptSetup implements Meecrowave.MeecrowaveAwareInstanceCustomizer {
+ private Meecrowave instance;
+
+ @Override
+ public void accept(final Tomcat tomcat) {
+ final ProtocolHandler protocolHandler = tomcat.getConnector().getProtocolHandler();
+ if (!AbstractHttp11Protocol.class.isInstance(protocolHandler)) {
+ return;
+ }
+
+ final LetsEncryptReloadLifecycle.LetsEncryptConfig config = instance.getConfiguration()
+ .getExtension(LetsEncryptReloadLifecycle.LetsEncryptConfig.class);
+ if (config.getDomains() == null || config.getDomains().trim().isEmpty()) {
+ return;
+ }
+
+ new LogFacade(getClass().getName()).info("Let's Encrypt extension activated");
+ tomcat.getHost().getPipeline().addValve(new LetsEncryptValve(AbstractHttp11Protocol.class.cast(protocolHandler), config));
+ }
+
+ @Override
+ public void setMeecrowave(final Meecrowave meecrowave) {
+ instance = meecrowave;
+ }
+}
Added: openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/java/org/apache/meecrowave/letencrypt/LetsEncryptValve.java
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/java/org/apache/meecrowave/letencrypt/LetsEncryptValve.java?rev=1835215&view=auto
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/java/org/apache/meecrowave/letencrypt/LetsEncryptValve.java (added)
+++ openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/java/org/apache/meecrowave/letencrypt/LetsEncryptValve.java Fri Jul 6 08:33:27 2018
@@ -0,0 +1,60 @@
+package org.apache.meecrowave.letencrypt;
+
+import static java.util.Optional.ofNullable;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.catalina.valves.ValveBase;
+import org.apache.coyote.http11.AbstractHttp11Protocol;
+
+public class LetsEncryptValve extends ValveBase {
+ private final AbstractHttp11Protocol<?> protocol;
+ private final LetsEncryptReloadLifecycle.LetsEncryptConfig config;
+ private LetsEncryptReloadLifecycle support;
+
+ private volatile Current current = new Current("/.well-known/acme-challenge/-", "none");
+
+ public LetsEncryptValve(final AbstractHttp11Protocol<?> protocol,
+ final LetsEncryptReloadLifecycle.LetsEncryptConfig config) {
+ super(true);
+ this.protocol = protocol;
+ this.config = config;
+ }
+
+ @Override
+ protected void initInternal() throws LifecycleException {
+ super.initInternal();
+ support = new LetsEncryptReloadLifecycle(config, protocol, (e, c) -> current = new Current(e, c));
+ }
+
+ @Override
+ protected synchronized void stopInternal() throws LifecycleException {
+ super.stopInternal();
+ ofNullable(support).ifPresent(LetsEncryptReloadLifecycle::close);
+ }
+
+ @Override
+ public void invoke(final Request request, final Response response) throws IOException, ServletException {
+ if (request.getRequestURI().equals(current.endpoint)) {
+ response.setHeader("Content-Type", "text/plain");
+ response.getWriter().write(current.challenge);
+ return;
+ }
+ getNext().invoke(request, response);
+ }
+
+ private static class Current {
+ private final String endpoint;
+ private final String challenge;
+
+ private Current(final String endpoint, final String challenge) {
+ this.endpoint = endpoint;
+ this.challenge = challenge;
+ }
+ }
+}
Added: openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/resources/META-INF/services/org.apache.meecrowave.runner.Cli$Options
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/resources/META-INF/services/org.apache.meecrowave.runner.Cli%24Options?rev=1835215&view=auto
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/resources/META-INF/services/org.apache.meecrowave.runner.Cli$Options (added)
+++ openwebbeans/meecrowave/trunk/meecrowave-letsencrypt/src/main/resources/META-INF/services/org.apache.meecrowave.runner.Cli$Options Fri Jul 6 08:33:27 2018
@@ -0,0 +1 @@
+org.apache.meecrowave.letencrypt.LetsEncryptReloadLifecycle$LetsEncryptConfig
Modified: openwebbeans/meecrowave/trunk/meecrowave-maven-plugin/pom.xml
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-maven-plugin/pom.xml?rev=1835215&r1=1835214&r2=1835215&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-maven-plugin/pom.xml (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-maven-plugin/pom.xml Fri Jul 6 08:33:27 2018
@@ -31,6 +31,7 @@
<properties>
<maven.version>3.3.9</maven.version>
+ <meecrowave.build.name>${project.groupId}.maven</meecrowave.build.name>
</properties>
<dependencies>
Modified: openwebbeans/meecrowave/trunk/meecrowave-oauth2/pom.xml
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-oauth2/pom.xml?rev=1835215&r1=1835214&r2=1835215&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-oauth2/pom.xml (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-oauth2/pom.xml Fri Jul 6 08:33:27 2018
@@ -28,6 +28,10 @@
<artifactId>meecrowave-oauth2</artifactId>
<name>Meecrowave :: OAuth2</name>
+ <properties>
+ <meecrowave.build.name>${project.groupId}.oauth2</meecrowave.build.name>
+ </properties>
+
<dependencies>
<dependency>
<groupId>org.apache.meecrowave</groupId>
Modified: openwebbeans/meecrowave/trunk/meecrowave-specs-api/pom.xml
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-specs-api/pom.xml?rev=1835215&r1=1835214&r2=1835215&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-specs-api/pom.xml (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-specs-api/pom.xml Fri Jul 6 08:33:27 2018
@@ -28,6 +28,10 @@
<artifactId>meecrowave-specs-api</artifactId>
<name>Meecrowave :: Specs API</name>
+ <properties>
+ <meecrowave.build.name>${project.groupId}.specs</meecrowave.build.name>
+ </properties>
+
<dependencies>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
Modified: openwebbeans/meecrowave/trunk/pom.xml
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/pom.xml?rev=1835215&r1=1835214&r2=1835215&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/pom.xml (original)
+++ openwebbeans/meecrowave/trunk/pom.xml Fri Jul 6 08:33:27 2018
@@ -47,6 +47,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <meecrowave.build.name>${project.groupId}.${project.artifactId}</meecrowave.build.name>
<junit.version>4.12</junit.version>
<tomcat.version>9.0.10</tomcat.version>
@@ -65,6 +66,7 @@
</properties>
<modules>
+ <module>meecrowave-specs-api</module>
<module>meecrowave-core</module>
<module>meecrowave-maven-plugin</module>
<module>meecrowave-gradle-plugin</module>
@@ -76,7 +78,7 @@
<module>meecrowave-jta</module>
<module>integration-tests</module>
<module>meecrowave-oauth2</module>
- <module>meecrowave-specs-api</module>
+ <module>meecrowave-letsencrypt</module>
</modules>
<dependencyManagement>
@@ -141,9 +143,24 @@
</configuration>
</plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>3.0.2</version>
+ <configuration>
+ <archive combine.children="append">
+ <manifestEntries>
+ <Automatic-Module-Name>${meecrowave.build.name}</Automatic-Module-Name>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ </plugin>
+
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
+ <version>2.22.0</version>
<configuration>
<trimStackTrace>false</trimStackTrace>
</configuration>