Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add newrelic ssl certificate if ca_bundle_path is not specified. Reso… #54

Merged
merged 4 commits into from
Sep 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,91 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.logging.Level;

public class ApacheSSLManager {
private static final String NEW_RELIC_CERT = "META-INF/newrelic-com.pem";


public static SSLContext createSSLContext(String caBundlePath) {
SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
try {
if (caBundlePath != null) {
sslContextBuilder.loadTrustMaterial(getKeyStore(caBundlePath), null);
} else {
addNewRelicCertToTrustStore(sslContextBuilder);
}

return sslContextBuilder.build();
} catch (Exception e) {
Agent.LOG.log(Level.WARNING, e, "Unable to create SSL context");
return null;
}
}

private static KeyStore getKeyStore(String caBundlePath) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
private static void addNewRelicCertToTrustStore(SSLContextBuilder sslContextBuilder)
throws KeyStoreException, CertificateException, NoSuchAlgorithmException {
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
URL nrCertUrl = ApacheSSLManager.class.getClassLoader().getResource(NEW_RELIC_CERT);
if (nrCertUrl != null) {
try (InputStream is = nrCertUrl.openStream()) {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
boolean sslCertIsValid = isSslCertValid(cert);
if (sslCertIsValid) {
logIfExpiringSoon(cert.getNotAfter());
// Initialize keystore and add valid New Relic certificate
keystore.load(null, null);
keystore.setCertificateEntry("newrelic", cert);
Agent.LOG.log(Level.FINEST, "Installed New Relic ssl certificate at alias: newrelic. ");
Agent.LOG.log(Level.FINEST, "SSL Certificate expires on: {0}", cert.getNotAfter());
}
} catch (IOException e) {
Agent.LOG.log(Level.INFO, "Unable to add bundled New Relic ssl certificate.", e);
}
} else {
Agent.LOG.log(Level.INFO, "Unable to find bundled New Relic ssl certificate.");
}
sslContextBuilder.loadTrustMaterial(keystore, null);
}

private static void logIfExpiringSoon(Date expiry) {
// log if less than 3 months left until certificate expires
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MONTH, +3);
if (cal.getTime().compareTo(expiry) > 0) {
Agent.LOG.log(Level.WARNING, "New Relic ssl certificate expire on {0}.\n" +
"Applications using a custom Trustore may need to update the agent " +
"or provide a valid certificate using the ca_bundle_path config", expiry);
}
}

private static boolean isSslCertValid(X509Certificate cert) {
try {
cert.checkValidity();
} catch (CertificateExpiredException | CertificateNotYetValidException e) {
Agent.LOG.log(Level.WARNING, "New Relic ssl certificate has expired.\n" +
"Applications using a custom Trustore may need to update the agent " +
"or provide a valid certificate using the ca_bundle_path config", e);
return false;
}
return true;
}

private static KeyStore getKeyStore(String caBundlePath)
throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
Agent.LOG.finer("SSL Keystore Provider: " + keystore.getProvider().getName());

Expand All @@ -54,7 +113,8 @@ private static KeyStore getKeyStore(String caBundlePath) throws KeyStoreExceptio
try {
caCerts.add((X509Certificate) cf.generateCertificate(is));
} catch (Throwable t) {
Agent.LOG.log(Level.SEVERE, "Unable to generate ca_bundle_path certificate. Will not process further certs.", t);
Agent.LOG.log(Level.SEVERE,
"Unable to generate ca_bundle_path certificate. Will not process further certs.", t);
break;
}
}
Expand Down
35 changes: 35 additions & 0 deletions newrelic-agent/src/main/resources/META-INF/newrelic-com.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
-----BEGIN CERTIFICATE-----
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
aSfWVsATwHjpT+pVxJLT47vYMlo=
-----END CERTIFICATE-----
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ public static Map<String, Object> createStagingMap(boolean https, boolean isHigh
map.put("host", "localhost");
map.put("port", MOCK_COLLECTOR_HTTPS_PORT);
map.put("license_key", "deadbeefcafebabe8675309babecafe1beefdead");
map.put("ca_bundle_path", "src/test/resources/server.cer");
map.put(AgentConfigImpl.APP_NAME, "MyApplication");
map.put(AgentConfigImpl.LABELS, "one:two;three:four");
if (isHighSec) {
Expand Down Expand Up @@ -1083,6 +1084,7 @@ public void testBadLicense() throws Exception {
map.put("host", "localhost");
map.put("port", MOCK_COLLECTOR_HTTPS_PORT);
map.put("license_key", "xxxxxxxxxxxxxxxxxxxxxxxxxxx");
map.put("ca_bundle_path", "src/test/resources/server.cer");
map.put(AgentConfigImpl.APP_NAME, "MyApplication");
createServiceManager(map);

Expand All @@ -1095,6 +1097,7 @@ public void testBadLicenseWithPut() throws Exception {
map.put("host", "localhost");
map.put("port", MOCK_COLLECTOR_HTTPS_PORT);
map.put("license_key", "xxxxxxxxxxxxxxxxxxxxxxxxxxx");
map.put("ca_bundle_path", "src/test/resources/server.cer");
map.put(AgentConfigImpl.APP_NAME, "MyApplication");
map.put(AgentConfigImpl.PUT_FOR_DATA_SEND_PROPERTY, true);
createServiceManager(map);
Expand Down