-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Issue #5019 - add class to do SSL keystore hot-reload in new module
Signed-off-by: Lachlan Roberts <[email protected]>
- Loading branch information
1 parent
94956d6
commit 24d0e50
Showing
3 changed files
with
175 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<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/maven-v4_0_0.xsd"> | ||
<parent> | ||
<groupId>org.eclipse.jetty</groupId> | ||
<artifactId>jetty-project</artifactId> | ||
<version>9.4.31-SNAPSHOT</version> | ||
</parent> | ||
<modelVersion>4.0.0</modelVersion> | ||
<artifactId>jetty-ssl-reload</artifactId> | ||
<name>Jetty :: SSL Reload</name> | ||
|
||
<properties> | ||
<bundle-symbolic-name>${project.groupId}.ssl.reload</bundle-symbolic-name> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.eclipse.jetty</groupId> | ||
<artifactId>jetty-util</artifactId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.eclipse.jetty</groupId> | ||
<artifactId>jetty-server</artifactId> | ||
<version>${project.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
</project> |
146 changes: 146 additions & 0 deletions
146
jetty-ssl-reload/src/main/java/org/eclipse/jetty/ssl/reload/SslKeyStoreScanner.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
// | ||
// ======================================================================== | ||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. | ||
// ------------------------------------------------------------------------ | ||
// All rights reserved. This program and the accompanying materials | ||
// are made available under the terms of the Eclipse Public License v1.0 | ||
// and Apache License v2.0 which accompanies this distribution. | ||
// | ||
// The Eclipse Public License is available at | ||
// http://www.eclipse.org/legal/epl-v10.html | ||
// | ||
// The Apache License v2.0 is available at | ||
// http://www.opensource.org/licenses/apache2.0.php | ||
// | ||
// You may elect to redistribute this code under either of these licenses. | ||
// ======================================================================== | ||
// | ||
|
||
package org.eclipse.jetty.ssl.reload; | ||
|
||
import java.io.File; | ||
import java.net.URI; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import org.eclipse.jetty.util.Scanner; | ||
import org.eclipse.jetty.util.annotation.ManagedAttribute; | ||
import org.eclipse.jetty.util.annotation.ManagedOperation; | ||
import org.eclipse.jetty.util.component.AbstractLifeCycle; | ||
import org.eclipse.jetty.util.log.Log; | ||
import org.eclipse.jetty.util.log.Logger; | ||
import org.eclipse.jetty.util.ssl.SslContextFactory; | ||
|
||
public class SslKeyStoreScanner extends AbstractLifeCycle implements Scanner.DiscreteListener | ||
{ | ||
private static final Logger LOG = Log.getLogger(SslKeyStoreScanner.class); | ||
|
||
private final SslContextFactory sslContextFactory; | ||
private final File keystoreFile; | ||
private final List<File> files = new ArrayList<>(); | ||
private Scanner _scanner; | ||
private int _scanInterval = 1; | ||
|
||
public SslKeyStoreScanner(SslContextFactory sslContextFactory) | ||
{ | ||
this.sslContextFactory = sslContextFactory; | ||
this.keystoreFile = new File(URI.create(sslContextFactory.getKeyStorePath())); // getKeyStorePath is giving url instead of path? | ||
if (!keystoreFile.exists()) | ||
throw new IllegalArgumentException("keystore file does not exist"); | ||
if (keystoreFile.isDirectory()) | ||
throw new IllegalArgumentException("expected keystore file not directory"); | ||
|
||
File parentFile = keystoreFile.getParentFile(); | ||
if (!parentFile.exists() || !parentFile.isDirectory()) | ||
throw new IllegalArgumentException("error obtaining keystore dir"); | ||
|
||
files.add(parentFile); | ||
if (LOG.isDebugEnabled()) | ||
LOG.debug("created {}", this); | ||
} | ||
|
||
@Override | ||
protected void doStart() throws Exception | ||
{ | ||
if (LOG.isDebugEnabled()) | ||
LOG.debug(this.getClass().getSimpleName() + ".doStart()"); | ||
|
||
_scanner = new Scanner(); | ||
_scanner.setScanDirs(files); | ||
_scanner.setScanInterval(_scanInterval); | ||
_scanner.setReportDirs(false); | ||
_scanner.setReportExistingFilesOnStartup(false); | ||
_scanner.setScanDepth(1); | ||
_scanner.addListener(this); | ||
_scanner.start(); | ||
} | ||
|
||
@Override | ||
protected void doStop() throws Exception | ||
{ | ||
if (_scanner != null) | ||
{ | ||
_scanner.stop(); | ||
_scanner.removeListener(this); | ||
_scanner = null; | ||
} | ||
} | ||
|
||
@Override | ||
public void fileAdded(String filename) throws Exception | ||
{ | ||
if (LOG.isDebugEnabled()) | ||
LOG.debug("added {}", filename); | ||
|
||
if (keystoreFile.toPath().toString().equals(filename)) | ||
reload(); | ||
} | ||
|
||
@Override | ||
public void fileChanged(String filename) throws Exception | ||
{ | ||
if (LOG.isDebugEnabled()) | ||
LOG.debug("changed {}", filename); | ||
|
||
if (keystoreFile.toPath().toString().equals(filename)) | ||
reload(); | ||
} | ||
|
||
@Override | ||
public void fileRemoved(String filename) throws Exception | ||
{ | ||
if (LOG.isDebugEnabled()) | ||
LOG.debug("removed {}", filename); | ||
|
||
// TODO: do we want to do this? | ||
if (keystoreFile.toPath().toString().equals(filename)) | ||
reload(); | ||
} | ||
|
||
@ManagedOperation(value = "Reload the SSL Keystore", impact = "ACTION") | ||
public void reload() throws Exception | ||
{ | ||
if (LOG.isDebugEnabled()) | ||
LOG.debug("reloading keystore file {}", keystoreFile); | ||
|
||
try | ||
{ | ||
sslContextFactory.reload(scf -> {}); | ||
} | ||
catch (Throwable t) | ||
{ | ||
LOG.warn("Keystore Reload Failed", t); | ||
} | ||
} | ||
|
||
@ManagedAttribute("scanning interval to detect changes which need reloaded") | ||
public int getScanInterval() | ||
{ | ||
return _scanInterval; | ||
} | ||
|
||
public void setScanInterval(int scanInterval) | ||
{ | ||
_scanInterval = scanInterval; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters