Update "ssl-config" to support X-Pack features#74887
Conversation
This commit upgrades the existing SSPL licensed "ssl-config" library to include additional features that are supported by the X-Pack SSL library. This commit does not make any changes to X-Pack to use these new features - it introduces them in preparation for their future use by X-Pack. The reindex module is updated to reflect API changes in ssl-config
|
Pinging @elastic/es-security (Team:Security) |
|
I've labelled this as |
| /** | ||
| * A TrustConfiguration that merges trust anchors from a number of other trust configs to produce a single {@link X509ExtendedTrustManager}. | ||
| */ | ||
| public class CompositeTrustConfig implements SslTrustConfig { |
There was a problem hiding this comment.
In X-Pack, specifying a keystore, but no truststore gives you a set of trust anchors that support everything in your JDK trust, and all the trust anchors in your keystore.
This class was added so we can also support that behaviour from ssl-config.
|
|
||
| @Override | ||
| public boolean isSystemDefault() { | ||
| return true; |
There was a problem hiding this comment.
This method needed for the PKI realm - it will not trust the JDK default issuers.
| * main/java/org/apache/jmeter/protocol/oauth/sampler/PrivateKeyReader.java | ||
| */ | ||
| final class DerParser { | ||
| public final class DerParser { |
There was a problem hiding this comment.
The RestrictedTrustConfig in X-Pack needs to be able to use this parser.
| * A variety of utility methods for working with or constructing {@link KeyStore} instances. | ||
| */ | ||
| final class KeyStoreUtil { | ||
| public final class KeyStoreUtil { |
There was a problem hiding this comment.
Some of these methods have been made public because X-Pack will need to call them.
| } | ||
|
|
||
| static Stream<KeyStoreEntry> stream(KeyStore keyStore, | ||
| Function<GeneralSecurityException, ? extends RuntimeException> exceptionHandler) { |
There was a problem hiding this comment.
This method and the class below were added to support stream-based iteration over keystore entires.
| throw SslFileUtil.ioException(KEY_FILE_TYPE, List.of(path), e); | ||
| } catch (GeneralSecurityException e) { | ||
| throw new SslConfigException("cannot load ssl private key file [" + key.toAbsolutePath() + "]", e); | ||
| throw SslFileUtil.securityException(KEY_FILE_TYPE, List.of(path), e); |
There was a problem hiding this comment.
Lots of exception handling has been unified. See comments in SslFileUtil
| /** | ||
| * Utility methods for common file handling in SSL configuration | ||
| */ | ||
| final class SslFileUtil { |
There was a problem hiding this comment.
This is a new class, mostly to handle generating exceptions for particular file related problems.
| return ioException(fileType, paths, cause, null); | ||
| } | ||
|
|
||
| static SslConfigException ioException(String fileType, List<Path> paths, IOException cause, String detail) { |
There was a problem hiding this comment.
One of the big things we did to try and make X-Pack SSL setup easier was write clear & explicit error messages for all the common problems that people run into:
- File not found
- File permissions wrong
- File in wrong directory
- Missing password
- Wrong password
This class replicates those messages into ssl-config and centralises them.
Some of the messages already existed in this library, but the X-Pack ones are encountered more frequently, and have been better turned for readability.
That said, I did try and improve some of them along the way.
| import java.util.Objects; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| public abstract class SslKeystoreConfig implements SslKeyConfig { |
There was a problem hiding this comment.
This is a base class for PKCS#11 and File-Keystore (JKS, PKCS#12) support.
The X-Pack model of having 1 class that handled both was really fragile - we often wrote code that assume that the file was non-null.
| * Information about a certificate that is locally stored.It includes a reference to the {@link X509Certificate} itself, | ||
| * as well as information about where it was loaded from. | ||
| */ | ||
| public class StoredCertificate { |
There was a problem hiding this comment.
This is used for the _ssl/certificates API.
That API uses a CertificateInfo which depends on ToXContent etc, which isn't available inside this library. So this class is a lightweight representation of the information needed for that API, and X-Pack will convert from this class to the X-Pack class.
|
@elasticmachine update branch |
BigPandaToo
left a comment
There was a problem hiding this comment.
I added a couple of nit comments.
LGTM otherwise
|
|
||
| /** | ||
| * Construct an in-memory keystore with multiple trusted cert entries. | ||
| * |
There was a problem hiding this comment.
I wouldn't say so.
Everything in that file has blank line between the method description & the parameters, so this format is consistent with the rest of the code.
libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslKeystoreConfig.java
Outdated
Show resolved
Hide resolved
jkakavas
left a comment
There was a problem hiding this comment.
Thanks for taking the time to add comments for things that would most probably raise questions, that was very helpful. Added some suggestions and comments, mostly nits
| * @param keyPassword Password for the private key (or empty is the key is not encrypted) | ||
| * @param configBasePath The base directory from which config files should be read (used for diagnostic exceptions) | ||
| */ | ||
| public PemKeyConfig(String certificate, String key, char[] keyPassword, Path configBasePath) { |
There was a problem hiding this comment.
nit for readability
| public PemKeyConfig(String certificate, String key, char[] keyPassword, Path configBasePath) { | |
| public PemKeyConfig(String certificatePath, String key, char[] keyPassword, Path configBasePath) { |
| boolean first = true; | ||
| for (Certificate cert : certificates) { | ||
| if (cert instanceof X509Certificate) { | ||
| info.add(new StoredCertificate((X509Certificate) cert, this.certificate, "PEM", null, first)); |
There was a problem hiding this comment.
is it safe to assume that certificate points to a file where if multiple certs are included, the leaf is always the first one?
There was a problem hiding this comment.
Probably not - but that's what X-Pack currently does.
It should be - if the certificate path points to a PEM file with multiple certificates, then they should be a chain ordered from leaf to issuer to root - but there's no guarantee that it's true.
However, other things will break if it's not. When we build a keystore we will assume the certificates that we read form a valid chain, and Keystore.setKeyEntry will throw an exception if they're not.
There was a problem hiding this comment.
I added a test to show that createKeyManager fails if the chain is in the wrong order. I think that is sufficient for the assumption in this method.
We do have a "private key" for the leaf (first element) certificate. It might be the wrong key (none of the config classes check that in this method), but we have one.
And the core functionality of the config (building a key manager) will fail.
libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/KeyStoreUtil.java
Show resolved
Hide resolved
libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/KeyStoreUtil.java
Show resolved
Hide resolved
| final Path trustStorePath = resolveSetting(TRUSTSTORE_PATH, basePath::resolve, null); | ||
| protected SslTrustConfig buildTrustConfig(Path basePath, SslVerificationMode verificationMode, SslKeyConfig keyConfig) { | ||
| final List<String> certificateAuthorities = resolveListSetting(CERTIFICATE_AUTHORITIES, Function.identity(), null); | ||
| final String trustStorePath = resolveSetting(TRUSTSTORE_PATH, Function.identity(), null); |
| if (cause.getMessage() != null) { | ||
| message += " (" + cause.getMessage() + ")"; | ||
| } | ||
| if (detail != null) { |
There was a problem hiding this comment.
is it worth adding the hint about UnrecoverableKeyException ? ( maybe only if detail is null )
| /** | ||
| * @return A collection of {@link X509Certificate certificates} used by this config. | ||
| */ | ||
| Collection<? extends StoredCertificate> getConfiguredCertificates(); |
There was a problem hiding this comment.
Do we foresee exteding StoredCertificate ? Can we make the return type non generic for now ?
| List<Tuple<PrivateKey, X509Certificate>> getKeys(); | ||
|
|
||
| /** | ||
| * @return A collection of {@link X509Certificate certificates} used by this config. |
There was a problem hiding this comment.
nit: update javadoc with corret return type
| if (certificates.isEmpty()) { | ||
| return List.of(); | ||
| } | ||
| final Certificate certificate = certificates.get(0); |
There was a problem hiding this comment.
nit: rename certificate here for readability ( vs this.certificate)
|
|
||
| if (cause.getCause() instanceof UnrecoverableKeyException) { | ||
| message += " - this is usually caused by an incorrect password"; | ||
| } else if (cause != null && cause.getMessage() != null) { |
There was a problem hiding this comment.
cause can't be null here, otherwise we'd have thrown an NPE in cause.getCause() above. We can check that cause is not null above and not go into this conditional at all
- Remove PKCS#11 - Improve exception messages - Simplify return types
PemKeyConfig.getConfiguredCertificates relies on the certificate file containing a chain from leaf -> issuer -> .. -> root This commit adds a test to ensure that createKeyManager will fail if that order is not correct, and therefore the assumption in getConfiguredCertificates is acceptable
This commit upgrades the existing SSPL licensed "ssl-config" library to include additional features that are supported by the X-Pack SSL library. This commit does not make any changes to X-Pack to use these new features - it introduces them in preparation for their future use by X-Pack. The reindex module is updated to reflect API changes in ssl-config
This commit upgrades the existing SSPL licensed "ssl-config" library to include additional features that are supported by the X-Pack SSL library. This commit does not make any changes to X-Pack to use these new features - it introduces them in preparation for their future use by X-Pack. The reindex module is updated to reflect API changes in ssl-config
This commit upgrades the existing SSPL licensed "ssl-config" library
to include additional features that are supported by the X-Pack SSL
library.
This commit does not make any changes to X-Pack to use these new
features - it introduces them in preparation for their future use by
X-Pack.
The reindex module is updated to reflect API changes in ssl-config