com.redhat.insights.tls.PEMSupport Maven / Gradle / Ivy
/* Copyright (C) Red Hat 2022-2023 */
package com.redhat.insights.tls;
import static com.redhat.insights.InsightsErrorCode.*;
import com.redhat.insights.InsightsException;
import com.redhat.insights.config.InsightsConfiguration;
import com.redhat.insights.logging.InsightsLogger;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.List;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import org.wildfly.common.iteration.CodePointIterator;
import org.wildfly.security.pem.Pem;
public class PEMSupport {
private final InsightsLogger logger;
private final InsightsConfiguration configuration;
public PEMSupport(InsightsLogger logger, InsightsConfiguration configuration) {
this.logger = logger;
this.configuration = configuration;
}
public SSLContext createTLSContext() {
if (!configuration.useMTLS()) {
throw new InsightsException(
ERROR_SSL_CREATING_CONTEXT, "Illegal attempt to create SSLContext for token auth");
}
byte[] certBytes = getBytesPossiblyPrivileged("--cert");
byte[] keyBytes = getBytesPossiblyPrivileged("--key");
if (certBytes.length == 0 || keyBytes.length == 0) {
throw new InsightsException(
ERROR_SSL_READING_CERTS, "SSLContext creation error - could not get file bytes");
}
logger.debug("Cert and key obtained successfully, trying to create TLS context");
return createTLSContext(certBytes, keyBytes);
}
// For low-level testing only
public SSLContext createTLSContext(Path certificatePath, Path keyPath) {
if (!Files.exists(certificatePath)) {
throw new InsightsException(
ERROR_SSL_CREATING_CONTEXT, "The certificate file does not exist: " + certificatePath);
}
if (!Files.exists(keyPath)) {
throw new InsightsException(
ERROR_SSL_CREATING_CONTEXT, "The key file does not exist: " + certificatePath);
}
try {
byte[] certBytes = Files.readAllBytes(certificatePath);
byte[] keyBytes = Files.readAllBytes(keyPath);
return createTLSContext(certBytes, keyBytes);
} catch (Exception err) {
throw new InsightsException(ERROR_SSL_CREATING_CONTEXT, "SSLContext creation error", err);
}
}
byte[] getBytesPossiblyPrivileged(String mode) {
// First determine the path to look for
String pathStr = "";
switch (mode) {
case "--cert":
pathStr = configuration.getCertFilePath();
break;
case "--key":
pathStr = configuration.getKeyFilePath();
break;
default:
throw new InsightsException(
ERROR_SSL_READING_CERTS_INVALID_MODE,
"Invalid mode " + mode + " passed for cert retrieval. This should not happen.");
}
try {
return Files.readAllBytes(Paths.get(pathStr));
} catch (IOException iox) {
// Direct read failed - try to use the helper, if configured
logger.debug("Direct read of cert and key failed.", iox);
logger.debug(
"Trying to use the helper binary "
+ configuration.getCertHelperBinary()
+ " to read default cert: "
+ InsightsConfiguration.DEFAULT_RHEL_CERT_FILE_PATH
+ " and key: "
+ InsightsConfiguration.DEFAULT_RHEL_KEY_FILE_PATH);
CertHelper helper = new CertHelper(logger, configuration);
try {
return helper.readUsingHelper(mode);
} catch (IOException | InterruptedException e) {
throw new InsightsException(ERROR_SSL_CREATING_CONTEXT, "SSLContext creation error", e);
}
}
}
SSLContext createTLSContext(byte[] certPemData, byte[] keyPemData) {
char[] keystorePassword = new char[0];
try {
Certificate[] certificates =
parsePemData(Certificate.class, certPemData).toArray(new Certificate[0]);
List keys = parsePemData(PrivateKey.class, keyPemData);
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
for (int i = 0; i < certificates.length; i++) {
keyStore.setCertificateEntry("cert-" + i, certificates[i]);
}
for (int i = 0; i < keys.size(); i++) {
keyStore.setKeyEntry("key-" + i, keys.get(i), keystorePassword, certificates);
}
KeyManagerFactory keyManagerFactory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keystorePassword);
SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
sslContext.init(keyManagerFactory.getKeyManagers(), null, null);
return sslContext;
} catch (CertificateException err) {
throw new InsightsException(ERROR_SSL_CERTS_PROBLEM, "Certificates error", err);
} catch (UnrecoverableKeyException
| KeyStoreException
| IOException
| NoSuchAlgorithmException
| KeyManagementException err) {
throw new InsightsException(ERROR_SSL_CREATING_CONTEXT, "SSLContext creation error", err);
}
}
private static List parsePemData(Class type, byte[] data) {
ArrayList items = new ArrayList<>();
Pem.parsePemContent(CodePointIterator.ofUtf8Bytes(data))
.forEachRemaining(
pemEntry -> {
T cast = pemEntry.tryCast(type);
if (cast == null) {
throw new InsightsException(
ERROR_SSL_PARSING_CERTS,
"Could not cast the a PemEntry of type " + type + " to class " + type);
}
items.add(cast);
});
return items;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy