Skip to content

Commit

Permalink
Have KeyStoreUtil.updateWithServerPems load the full cert chain
Browse files Browse the repository at this point in the history
updateWithServerPems uses CertificateFactory.GenerateCertificate(), which only loads the
first certificate in the server certificate file. When using a certificate that is signed by
an intermediate CA (like Let's Encrypt,) this would result in a certifiacte that won't be
accepted by clients that only has the root CA, and not the intermediate CA, in their trusted
certificates stores.

This replaces that call with a call to CertificateFactory.GenerateCertificates(), that
loads the full chain, allowing clients with just the root chain to trust the server.

Signed-off-by: Shay Elkin <shay@elkin.io>
  • Loading branch information
shayelkin committed Apr 4, 2024
1 parent 9fc1b95 commit 58e9799
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public static void updateWithServerPems(KeyStore pKeyStore, File pServerCert, Fi
throws IOException, CertificateException, NoSuchAlgorithmException, InvalidKeySpecException, KeyStoreException {
try (InputStream is = new FileInputStream(pServerCert)) {
CertificateFactory certFactory = CertificateFactory.getInstance("X509");
X509Certificate cert = (X509Certificate) certFactory.generateCertificate(is);
Certificate[] certificates = certFactory.generateCertificates(is).toArray(new Certificate[1]);

byte[] keyBytes = decodePem(pServerKey);
PrivateKey privateKey;
Expand All @@ -101,8 +101,8 @@ public static void updateWithServerPems(KeyStore pKeyStore, File pServerCert, Fi
privateKey = keyFactory.generatePrivate(keySpec);
}

String alias = cert.getSubjectX500Principal().getName();
pKeyStore.setKeyEntry(alias, privateKey, pPassword, new Certificate[]{cert});
String alias = ((X509Certificate) certificates[0]).getSubjectX500Principal().getName();
pKeyStore.setKeyEntry(alias, privateKey, pPassword, certificates);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateCrtKey;
Expand Down Expand Up @@ -126,6 +127,39 @@ public void testKeyStore() throws IOException, CertificateException, NoSuchAlgor
assertEquals("RSA", pubKey.getAlgorithm());
}

@Test
public void testKeyStoreWithCertChain() throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, InvalidKeySpecException, UnrecoverableKeyException {
File serverPem = getTempFile("server/server-chain.pem");
File keyPem = getTempFile("server/key.pem");
KeyStore keystore = createKeyStore();

KeyStoreUtil.updateWithServerPems(keystore, serverPem, keyPem, "RSA", new char[0]);

List<String> aliases = asList(keystore.aliases());
assertEquals(aliases.size(), 1);
String alias = aliases.get(0);
assertTrue(alias.contains("server"));

Certificate[] chain = keystore.getCertificateChain(alias);
assertEquals(chain.length, 3);

String[] expectedSubjectDNs = new String[]{
SERVER_CERT_SUBJECT_DN,
"CN=Intermediate CA, OU=Test, O=jolokia.org, L=Mountain View, ST=California, C=US",
"CN=Root CA, OU=Test, O=jolokia.org, L=Mountain View, ST=California, C=US"
};

for (int i = 0; i < expectedSubjectDNs.length; i++) {
assertEquals(((X509Certificate) chain[i]).getSubjectDN().getName(), expectedSubjectDNs[i]);
RSAPublicKey pubKey = (RSAPublicKey) chain[i].getPublicKey();
assertEquals("RSA", pubKey.getAlgorithm());
}

X509Certificate serverCert = (X509Certificate) chain[0];
RSAPrivateCrtKey key = (RSAPrivateCrtKey) keystore.getKey(alias, new char[0]);
assertEquals("RSA", key.getAlgorithm());
}

@Test
public void testBoth() throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, InvalidKeySpecException, InvalidKeyException, NoSuchProviderException, SignatureException {
File caPem = getTempFile("ca/cert.pem");
Expand Down
67 changes: 67 additions & 0 deletions agent/jvm/src/test/resources/certs/server/server-chain.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
-----BEGIN CERTIFICATE-----
MIID4jCCAsqgAwIBAgIUPsDvBHsHxtohcG2Bkq8vsw01juQwDQYJKoZIhvcNAQEL
BQAweTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM
DU1vdW50YWluIFZpZXcxFDASBgNVBAoMC2pvbG9raWEub3JnMQ0wCwYDVQQLDARU
ZXN0MRgwFgYDVQQDDA9JbnRlcm1lZGlhdGUgQ0EwHhcNMjQwNDA0MDQyNjUwWhcN
MjUwNDA0MDQyNjUwWjCBmDEUMBIGA1UEChMLam9sb2tpYS5vcmcxDTALBgNVBAsT
BFRlc3QxEDAOBgNVBAcTB1BlZ25pdHoxEjAQBgNVBAgTCUZyYW5jb25pYTELMAkG
A1UEBhMCREUxPjA8BgNVBAMTNVNlcnZlciBDZXJ0IHNpZ25lZCBhbmQgd2l0aCBl
eHRlbmRlZCBrZXkgdXNhZ2Ugc2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEA2RsfLKuprHOKiNWQMWXLz/0dwv0y9XKel+m0szzYm1+NffnH6etK
fR6dvrPL538Ny5IJ8qFXfuUg6qQ3JwC1DdVqPl3SZ2kv/P+1stX2285S+WUK7jH5
M77flZAIFhZLI7Lp46r58QL3H/Ok97iasyOdjo7idPmmu9OZLLBJMtTpp0MISgTY
70bT5EkNuKWCPzwo15bfBCDrJ1BrasRoQaEnsvV7noUwWiGzqM2YnGtGb7lpLuJH
RwffViohVxxUD4sr9CDn66YyZwwcq0Xim1JVK3RqQ3VxCszrejqFjHeGZRrjjBIf
4i2jAdHfn9WUG341XPqBKqrqDcuvH5p0BwIDAQABo0IwQDAdBgNVHQ4EFgQUh8Hn
a4fMpfDgrn6FD0uebT239yQwHwYDVR0jBBgwFoAUCxGvRp1jdfw1yUB3zkUPLqMo
BHowDQYJKoZIhvcNAQELBQADggEBAKJjXjo21rnHJINyr7FdRXzxRQtOg+6iJrGJ
tM+T3jEoaJwZeuwYWa2Gn/rlJlRH+vBnGFxnJ0obdQm+qn1G3H08GayUcx6151fS
qWo1mk+dP3cvx++YBnLBh6t+pphp6IKYHcCWwwKS6BmVgaKTyS2p6+FEL+0hulng
TAaZtvnKqQvBJllyfOHwhndkw/y/8v+jIHj8rEn5CNOFhO6VzjOzmTR30/JkEvpH
dgNR7nnrznPHDgyalOUtKepE+ehrWIiydr+rZSMVwOx1aCd6h4h5DdXYwJIZ1OoS
JFNddJbWtoO4x+x69JcarFjt/4IQ+rwRten4pxYXjjR5j+QGRS0=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDujCCAqKgAwIBAgIUHtoGroSz/WIYQBSPucdGlEI0z1UwDQYJKoZIhvcNAQEL
BQAwcTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM
DU1vdW50YWluIFZpZXcxFDASBgNVBAoMC2pvbG9raWEub3JnMQ0wCwYDVQQLDARU
ZXN0MRAwDgYDVQQDDAdSb290IENBMB4XDTI0MDQwNDA0MjEzNloXDTI1MDQwNDA0
MjEzNloweTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNV
BAcMDU1vdW50YWluIFZpZXcxFDASBgNVBAoMC2pvbG9raWEub3JnMQ0wCwYDVQQL
DARUZXN0MRgwFgYDVQQDDA9JbnRlcm1lZGlhdGUgQ0EwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQDLMH+ZJzF2fRibxh4uv65ab7g8cueYK+mQ9d8eTKsi
4jkv8kYt1YvOAU2Qjz0kU0rTD6BDyavNQ1rwwUSxO3pO52gL7bgptP4qXoA9xVa1
AWCPr7mvwZdti+oNZxsA++5H8RpfCTD9RRKz2Hhg35Putm6LL9eDaUSXrcSs809W
aUSbrQt+UWi+rvGV+u/iH5wnrNNlEy0eIbTmcdyS8wS1THZQrYD7f7Lo7BfYH1F2
VqNWPTmB+jPBkJcJiBDo3sykOikTD+qK81MXLhtgadqogYSoJBmRHk30rnL1K1yb
/h1ZQZlEzPRnrFuc4KEzwzdrxmPiHkGMFceT5+ez3xoDAgMBAAGjQjBAMB0GA1Ud
DgQWBBQLEa9GnWN1/DXJQHfORQ8uoygEejAfBgNVHSMEGDAWgBS4UHdWYsHX0oEu
CWMlNdJsqkN8cDANBgkqhkiG9w0BAQsFAAOCAQEAdgX5lVvk7dpPj/DjdXjVVdUE
FjpLfdUxZYwg7CW4a93EJCTRd9fbqRo/wZp36QDQZkD1CD1YgEBLQF/jPyVYxvPs
5YwT6BmvVrpA4NKW+cUic/brdfxv3/ZLE0w086j1ym7DVuGqMkMteYsZ63oZ7AIy
h1fBcqVtIVwnorPs9I/3WA9fH7kDGQUhWjTIVQt22nClzd9fgEu6U4YauCaKSnPS
ETzbHq94GF4dJ4wkr7dj+rC1DocmdiOlKi/IlpqPwnR+Z4HJV+osmlTAvc+qY+d1
IlxP2tpxF85GdUKtgiEzJ0KMB7fyi5NpMFLZ8ak3bG8PIlXOY/QITQJsaTczRw==
-----END CERTIFICATE-----
-----BEGIN TRUSTED CERTIFICATE-----
MIIDkTCCAnmgAwIBAgIUUuPglg/zLFqw0ipFE3IBzlIGFKQwDQYJKoZIhvcNAQEL
BQAwcTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM
DU1vdW50YWluIFZpZXcxFDASBgNVBAoMC2pvbG9raWEub3JnMQ0wCwYDVQQLDARU
ZXN0MRAwDgYDVQQDDAdSb290IENBMB4XDTI0MDQwNDA0MTk1NFoXDTI1MDQwNDA0
MTk1NFowcTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNV
BAcMDU1vdW50YWluIFZpZXcxFDASBgNVBAoMC2pvbG9raWEub3JnMQ0wCwYDVQQL
DARUZXN0MRAwDgYDVQQDDAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEA0NfuxrT0q5xB2HvUkvo8+d+fxEiy0zQ8+A6MnrRnj01P+TE4o6HI
ge1GXY+h5DijVdughu2seDeGgU0/vxIOi2J3ltDhZ6RQhkR4UCnAEsOp+OQEE96Z
DPONByFmo9RZR1fidwR6N9OigrgUJ0HT1bqMCsuV4RVRzB+bh4c/i29dIIcvmJGE
4yInM9HGx9fp26oCrJgbYrYbysjeQUo8gyk4f9feqnaORWZzsBBrbou59DWg1RCp
Hh1B+psfQtbetJoVOz/C1Rvz4ODwpscAV9L/KX4FtQuZUcCsDoCl/L0z328D9EqR
YdioXMUJ/WCgn5k1765qSgqM0YrS7ndFDQIDAQABoyEwHzAdBgNVHQ4EFgQUuFB3
VmLB19KBLgljJTXSbKpDfHAwDQYJKoZIhvcNAQELBQADggEBAI5TBKXyjmQiruSD
PI6pBzHwlkw2Is2Uh/SPN1d+QavXpdRKP+zRs936eigipm+y5GALUXN2L7rxjr3z
6sVqviPSyJqWAxjy02dI8O9M5rWIT1saRr7oddLAW07uLNXfczmY+R1aAIFdYmeY
dDRhBm2328+8Xc6mQbc44Fml0SkwY0lhzbBM5M5Ryx8q32Nqviv02tLMNREnnCo8
YE5AC0UZIAPL3kdMgP9fgOKRQcedX3/xd4Kb2m/OYXnp+bYayaNUFsHR9dfCWB2b
dE5CIzwj50kNG8MkcjhfWGQAgl+9TmshS7BgmWC1YXBNqkPfkMZfqg4+ZZ5r73uK
b4a1UAg=
-----END TRUSTED CERTIFICATE-----

0 comments on commit 58e9799

Please sign in to comment.