A certificate manager is an alternative to
EmbeddedWebServer.SSLSetup
and, in addition to configuring
an EmbeddedWebServer
for HTTPS, a certificate manager
automatically creates certificates and automatically renews them.
Callers should used the methods newInstance()
or newInstance(String)
to create an instance of
this class. When an argument is provided, it is either the fully-qualified
class name of the desired certificate manager, the string "default" for
a certificate manager that will provide a self-signed certificate, or
the string "external" if another process manages the keystore.
When newInstance()
, the first instance found using
the Java service loader is returned and if there are no such instances,
an instance of the default certificate manager is returned.
To configure the instance, use the methods
setCertName(String)
. This provides an identifier to name a certificate. Some instances require this.setDomain(String)
. This provides the domain name used in a certificate.setEmail(String)
. This provides an email address used to contact a user for administrative purposes (e.g., if a certificate is about to expire).setTimeOffset(int)
. This provides a time offset in seconds from midnight and is used to schedule checks for expired certificates at a time at which the server is not likely to be busy: the server has to be stopped temporarily to install new certificates.setInterval(int)
. This provides an interval in days between certificate renewal attempts. A certificate will not be renewed if it is not close to expiring. If set to zero, the value will be treated as one minute, which is useful for testing but not for actual use.setStopDelay(int)
. This provides the time in seconds to wait before fully shutting down a server when necessary to renew certificates.setProtocol(String)
. This provides the HTTPS protocol (e.g., SSL or TLS).setKeystoreFile(File)
. This provides a keystore file that will be used to store certificates using the alias "servercert". If the file does not exist, a new one will be created with a certificate.setTruststoreFile(File)
. This provides a trust store file to allow the user to specify additional root certificates. It may be null if no trust store is desired.setKeystorePW(char[])
. This provides the store password for a keystore as specified by keytool. The default password is "changeit".setKeyPW(char[])
. This provides the key password for a keystore as specified by keytool. The default password is the 'store' password.setTruststorePW(char[])
. This provides the store password for the trust store.setConfigurator(EmbeddedWebServer.Configurator)
. This sets an SSL Configurator as specified byEmbeddedWebServer.SSLSetup.configurator(EmbeddedWebServer.Configurator)
.setTracer(Appendable)
. This provides anAppendable
for tracing/logging.setCertTrace(boolean)
. This indicates if new certificates should be be printed or not anAppendable
for tracing has been configured.setHelper(EmbeddedWebServer)
. This provides a 'helper' HTTP server that some certificate managers require. While these certificate managers will create such a server, one created with this method can run continuously.
CertManager
on which they are called so
that one can write code such as
CertManager cm = CertManager.newInstance() .setInterval(7) .setTimeOffset(4*3600) ...
The newInstance methods use a ServiceLoader
to create instances of CertManager
. Each must contain a zero
argument constructor and implement the following methods:
providerName()
to provide a name for a manager that is
more mnemonic than its class name, the method
configureHelper(EmbeddedWebServer)
to configure
an HTTP server (that is not running) for use by the provider, and the
method helperPort()
to indicate the port on which
an HTTP server should run, with 0 indicating that such a server is not
needed.
As usual, the module-info file for a subclass SUBCLASS should contain the line
(using the fully-qualified name for SUBCLASS) and the META-INF/services directory in the JAR file should contain a file named org.bzdev.ejws.CertManager whose contents also includeprovides org.bzdev.ejws.CertManager with SUBCLASS;
(Tests indicate that some [all?] versions of Java will not recognize service providers found on the class path if a META-INF/services entry does not exist, so while redundant, including both is safer.)SUBCLASS
-
Nested Class Summary
Nested Classes -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionboolean
Determine if certificates should always be created instead of being reused until they are close to expiring.alwaysCreate
(boolean mode) Set if certificates should always be created instead of being reused until they are close to expiring.protected abstract boolean
Determine the status of a previously issued call torequestCertificate()
.protected void
configureHelper
(EmbeddedWebServer helper) Configure a helper HTTP server for use with this certificate manager.Get the certificate name.Get the domain name for a server.getEmail()
Get the email address.protected EmbeddedWebServer
Get a helper web server.long
Get the waiting time in milliseconds from when a server starts to the first time at which an attempt to renew a certificate is made.int
Get the number of days between attempts to renew certificates.long
Get the time interval between attempts to renew certificates.protected char[]
getKeyPW()
Get the key password for a keystore.Get the file for a keystore.protected char[]
Get the "store" password for a keystore.getMode()
Get the current mode.Set the protocol for the server to use.getSetup()
Get a configured instance ofEmbeddedWebServer.SSLSetup
.int
Get the delay for stopping a server.int
Get the time offset.Get the time-zone ID.protected Appendable
Get the currentAppendable
used for tracing.protected char[]
Set the "store" password for a truststore.int
Determine if a certificate manager needs an HTTP server to create a certificate, providing that server's TCP port.boolean
Test if certificates ares being monitored.static CertManager
Return a new instance ofCertManager
.static CertManager
newInstance
(String providerName) Return a new instance of a certificate manager given its name.Optional print name for a provider.Get the names of each available certificate manager.protected abstract boolean
Determine the status of a previously issued call torequestRenewal()
when that method generates a new certificate.protected abstract void
Request a certificate.protected abstract void
Request that a certificate be renewed.setCertName
(String name) Set the certificate name.setCertTrace
(boolean certTrace) Set whether or not certificates should be printed in tracesSet the SSL configurator.Set the domain name for a server.Set an email address for administrative emails.setHelper
(EmbeddedWebServer helper) Set a helper web server.setInterval
(int interval) Set the number of days between attempts to renew certificates.setKeyPW
(char[] pw) Set the key password for a keystore.setKeystoreFile
(File file) Set the file for a keystore.setKeystorePW
(char[] pw) Set the "store" password for a keystore.setMode
(CertManager.Mode mode) Set this certificate manager's mode.setProtocol
(String protocol) Set the protocol for the server to usesetStopDelay
(int stopDelay) Set the delay for stopping a server.setTimeOffset
(int offset) Set the time offset.setTimeZone
(String timezone) Set the time zone given a time-zone ID.setTimeZone
(TimeZone timezone) Set the time zone.setTracer
(Appendable tracer) Set anAppendable
to log various events.setTrustManagers
(TrustManager[] tms) Provide trust managers.setTruststoreFile
(File file) Provide a file containing a trust store.setTruststorePW
(char[] pw) Set the "store" password for a truststore.void
Start monitoring certificates for a servervoid
Stop monitoring certificates for a server.
-
Constructor Details
-
CertManager
public CertManager()
-
-
Method Details
-
setMode
Set this certificate manager's mode. This method should be used only when debugging or during preliminary testing.If not called, the default value is
CertManager.Mode.NORMAL
.- Parameters:
mode
- the mode; the default if null- Returns:
- this certificate manage
- See Also:
-
getMode
Get the current mode.- Returns:
- the mode
-
alwaysCreate
public boolean alwaysCreate()Determine if certificates should always be created instead of being reused until they are close to expiring. The default is false.- Returns:
- true if a certificate should always be created; false otherwise
-
alwaysCreate
Set if certificates should always be created instead of being reused until they are close to expiring. The default is false.This method's primary use is for testing so that any code written to renew a certificate is run as soon as a check for a renewal is made.
- Parameters:
mode
- true if a certificate should always be created; false otherwise- Returns:
- this certificate manage
-
newInstance
Return a new instance ofCertManager
. The instance returned will preferentially be the first one provided by a service loader. If the server loader cannot find an instance, an instance of the default certificate manager will be returned.- Returns:
- a new instance of
CertManager
.
-
providerNames
Get the names of each available certificate manager. A name is either "default" or the fully qualified class name of a certificate manager. A manager may be listed twice if it explicitly specifies a name. Explicitly specified names may be shared by more than one certificate manager.- Returns:
- the names of the certificate managers.
-
newInstance
Return a new instance of a certificate manager given its name.- Parameters:
providerName
- "default" for the default provider, "external" if another process manages certificats, or the fully qualified class name for the desired instance, a a provider name; or null for the first one available, excluding "default" and "external"
-
setTracer
Set anAppendable
to log various events.- Parameters:
tracer
- anAppendable
used to log events; null to disable logging- Returns:
- this
CertManager
-
getTracer
Get the currentAppendable
used for tracing.- Returns:
- the
Appendable
; null if there is none
-
setCertName
Set the certificate name. A certificate name is an identifier used to provide a readable name for a certificate. This may be used as part of a file name in some implementations.- Parameters:
name
- the name.- Returns:
- this
CertManager
-
getCertName
Get the certificate name.- Returns:
- the certificate name; null if there is none
-
setDomain
Set the domain name for a server. This will typically be the CN (Common Name) portion of a certificate's distinguished name.- Parameters:
domain
- the domain name (typically fully qualified or "localhost" for testing)- Returns:
- this
CertManager
-
getDomain
Get the domain name for a server.- Returns:
- the domain name
-
setEmail
Set an email address for administrative emails. This may be used for purposes such as notifications that a certificate is about to expire.- Parameters:
email
- the email address- Returns:
- this
CertManager
-
getEmail
Get the email address.- Returns:
- the email address
-
providerName
Optional print name for a provider. The default name for a provider is its fully qualified class name. This method provides an alternate name. It may not be unique and may represent groups of providers. Providers that use certbot should override this method to return the string "certbot". The names "default" and "external" are reserved and must not be used as new provider names.- Returns:
- the provider name; null if one is not explicitly provided
-
helperPort
public int helperPort()Determine if a certificate manager needs an HTTP server to create a certificate, providing that server's TCP port. For example, some implementations use the ACME protocol to obtain a certificate and use a server running HTTP on port 80 for that purpose. The default implementation returns 0, indicating that a server is not needed. If this method returns a non-zero value andsetHelper(EmbeddedWebServer)
was not called, a provider's implementation is expected to create a server running HTTP using the port returned by this method.- Returns:
- the TCP port if a web server is needed; 0 otherwise
-
configureHelper
Configure a helper HTTP server for use with this certificate manager. The default implementation of this method does nothing and should be overridden by providers such as ones that implement the ACME protocol, which requires a specific configuration for a server.This method will be called by
setHelper(EmbeddedWebServer)
when all of the following are true:-
helperPort()
returns a non-zero value. - the argument to
setHelper(EmbeddedWebServer)
is not null and is anEmbeddedWebServer
that is not running. - the server provided by the argument is an HTTP server, not an HTTPS server.
- Parameters:
helper
- the helper HTTP server
-
-
requestCertificate
protected abstract void requestCertificate()Request a certificate. When this method is called, the certificate should be placed in a keystore specified bysetKeystoreFile(File)
with an alias "servercert". An existing certificate should be returned unless it is about to expire, and if there is none, a new certificate should be created. This method may return before the operation is complete.Some providers of this class (e.g., ones using the ACME protocol) require a server running HTTP on a specified port. In this case, requestCertificate() should call
getHelper()
and if the result is not null, use that server. If that server is not running, requestCertificate() should ensure that any necessary prefixes have been added.If this certificate manager needs a helper and
getHelper()
returns null, this method must create the helper, configure it, start it, and shut it down before exiting. -
certificateRequestStatus
protected abstract boolean certificateRequestStatus()Determine the status of a previously issued call torequestCertificate()
. If the status is unknown, this method must block until the status can be determined.- Returns:
- true if a certificate is available; false otherwise
-
requestRenewal
protected abstract void requestRenewal()Request that a certificate be renewed. If a new certificate is available, this method must arrange forrenewalRequestStatus()
to returntrue
. This method andrenewalRequestStatus()
are called from different threads.If this certificate manager needs a helper and
getHelper()
returns null, this method must create the helper, configure it, start it, and shut it down before exiting. -
renewalRequestStatus
Determine the status of a previously issued call torequestRenewal()
when that method generates a new certificate. This method should normally block until it will returntrue
. It, andrequestRenewal()
, are called from different threads.- Returns:
- true if a new certificate is available; false if there was an error.
- Throws:
InterruptedException
-
setTimeOffset
Set the time offset. This is the time of the day in seconds at which attempts to renew certificates will be made. Time is measured from midnight using the server's time zone. The number of days between renewal attempts are set bysetInterval(int)
.If not called, the default value is 0.
- Parameters:
offset
- the time offset in seconds- Returns:
- this
CertManager
-
getTimeOffset
public int getTimeOffset()Get the time offset. This is the time of the day in seconds at which attempts to renew certificates will be made. Time is measured from midnight using the server's time zone. The number of days between renewal attempts are set bysetInterval(int)
.- Returns:
- the time offset in seconds.
-
setInterval
Set the number of days between attempts to renew certificates.If not called, the default value is 7.
- Parameters:
interval
- the interval in days.- Returns:
- this
CertManager
-
getInterval
public int getInterval()Get the number of days between attempts to renew certificates.- Returns:
- the interval in days
-
setStopDelay
Set the delay for stopping a server. WhenEmbeddedWebServer.stop(int)
is called, new requests are rejected immediately, and the delay indicates how long to wait for existing requests to be processed.If not called, the default value is 5.
- Parameters:
stopDelay
- the delay in seconds- Returns:
- this
CertManager
-
getStopDelay
public int getStopDelay()Get the delay for stopping a server. WhenEmbeddedWebServer.stop(int)
is called, new requests are rejected immediately, and the delay indicates how long to wait for existing requests to be processed.- Returns:
- the delay in seconds
-
setTimeZone
Set the time zone given a time-zone ID. The Java classTimeZone
provides a method to list the available time zone IDs. If the time zone ID is not recognized, the time zone will be set to GMT.If not called, the default value is the system default time zone.
- Parameters:
timezone
- the time zone ID (e.g, UTC or America/Los_Angeles); null or an empty string for the system default- Returns:
- this
CertManager
- See Also:
-
setTimeZone
Set the time zone.- Parameters:
timezone
- the time zone ID (e.g, UTC or America/Los_Angeles); null for the system default- Returns:
- this
CertManager
-
getTimeZone
Get the time-zone ID.- Returns:
- the time-zone ID for this object
-
getInitialWaitMillis
public long getInitialWaitMillis()Get the waiting time in milliseconds from when a server starts to the first time at which an attempt to renew a certificate is made.- Returns:
- the time interval in milliseconds
-
setCertTrace
Set whether or not certificates should be printed in traces- Parameters:
certTrace
- true if certificates should be printed; false otherwise- Returns:
- this
CertManager
-
getIntervalMillis
public long getIntervalMillis()Get the time interval between attempts to renew certificates.- Returns:
- the time interval in milliseconds
-
setProtocol
Set the protocol for the server to use- Parameters:
protocol
- the protocol (e.g., SSL or TLS) for HTTPS; null for HTTP- Returns:
- this
CertManager
-
getProtocol
Set the protocol for the server to use.- Returns:
- the protocol (e.g., SSL or TLS) for HTTPS; null for HTTP
-
setKeystoreFile
Set the file for a keystore. If the file does not exist, requests to get a certificate will create the file.- Parameters:
file
- the keystore file; null if there is no keystore- Returns:
- this
CertManager
-
getKeystoreFile
Get the file for a keystore. If the file does not exist, requests to get a certificate will create the file.- Returns:
- the file; null if there is no keystore
-
setTrustManagers
Provide trust managers.- Parameters:
tms
- the trust managers; null too cancel- Returns:
- this object
- Throws:
IllegalStateException
- if a {#link #t\setTrusstoreFile} was called with a non-null value- See Also:
-
setTruststoreFile
Provide a file containing a trust store.- Parameters:
file
- a file containing a trust store; null to cancel- Returns:
- this object
- Throws:
IllegalStateException
- iftrustManagers
has been called with a non-null value- See Also:
-
setKeystorePW
Set the "store" password for a keystore. The default password is "changeit".- Parameters:
pw
- the password; null for the default- Returns:
- this
CertManager
-
getKeystorePW
protected char[] getKeystorePW()Get the "store" password for a keystore.- Returns:
- the password; null if there is none
-
setKeyPW
Set the key password for a keystore.- Parameters:
pw
- the password; null to use the store password- Returns:
- this
CertManager
- See Also:
-
getKeyPW
protected char[] getKeyPW()Get the key password for a keystore.- Returns:
- the password; the keystore password if no key password has been explicitly provided
-
setTruststorePW
Set the "store" password for a truststore.- Parameters:
pw
- the password; null if there is none- Returns:
- this
CertManager
-
getTruststorePW
protected char[] getTruststorePW()Set the "store" password for a truststore.- Returns:
- pw the password; null if there is none
-
setConfigurator
Set the SSL configurator. Configurators are instance of the functional interfaceEmbeddedWebServer.Configurator
, and will typically be provided by a lambda expression that takes two arguments: an instance ofSSLContext
and an instance ofHttpsParameters
. These two arguments are provided by theHttpsServer
implementation.- Parameters:
c
- the configurator- Returns:
- this
CertManager
-
getHelper
Get a helper web server. Certificate authorities such as Lets-Encrypt use the ACME protocol for managing certificates ( RFC 8555), and these may make use of a separate web server using HTTP instead of HTTPS and typically running on port 80. This method returns anEmbeddedWebServer
that can be used for such purposes. When provided, the methodrequestCertificate()
is expected to start the helper if it is not already running and will start the helper after adding any prefixes needed as part of the process of obtaining a certificate.When this method returns null,
requestCertificate()
andrequestRenewal()
are expected to create a helper if needed, but will usually shut this helper down before returning.- Returns:
- the web server; null if none is provided
-
setHelper
Set a helper web server. Certificate authorities such as Lets-Encrypt use the ACME protocol for managing certificates ( RFC 8555), and these may make use of a separate web server using HTTP instead of HTTPS and running on port 80. This method allows the caller to provide anEmbeddedWebServer
that can be used for such purposes, with the added benefit of configuring additional prefixes to handle the case where a client is given a URL whose scheme is HTTP instead of HTTPS.If all of the following are true
- the argument to this method is not null,
-
helperPort()
returns a non-zero value, - the helper server is not an HTTPS server,
- the helper server is not currently running,
If a server is configured with this
CertManager
and that server is shut down, the helper will also be shut down and cannot be reused. As a result, aCertManager
that provides a helper should be used with only a singleEmbeddedWebServer
. Certificate manager providers should not try to start a helper that is already running. It is a good practice to let the provider start the helper.- Parameters:
helper
- the embedded web server to use; null (the default) if none is provided- Returns:
- this
CertManager
- See Also:
-
getSetup
Get a configured instance ofEmbeddedWebServer.SSLSetup
. Various methods provided by this class duplicate those provided byEmbeddedWebServer.SSLSetup
.Calling this method will also create keystore file and a certificate if one is not already available.
- Returns:
- a configured instance
EmbeddedWebServer.SSLSetup
- Throws:
IOException
-
isMonitoring
public boolean isMonitoring()Test if certificates ares being monitored.- Returns:
- true if certificates are being monitored; false otherwise
-
startMonitoring
Start monitoring certificates for a server- Parameters:
ews
- the server whose certificates are to be monitored
-
stopMonitoring
public void stopMonitoring()Stop monitoring certificates for a server.
-