Skip to content

Commit c62a018

Browse files
committed
Align buildpack certificate and key parsers with SSL versions
Closes gh-37969
1 parent 8f72f03 commit c62a018

File tree

8 files changed

+383
-336
lines changed

8 files changed

+383
-336
lines changed

spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/ssl/KeyStoreFactory.java

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
2626
import java.security.PrivateKey;
2727
import java.security.cert.CertificateException;
2828
import java.security.cert.X509Certificate;
29+
import java.util.List;
2930

3031
/**
3132
* Utility methods for creating Java trust material from key and certificate files.
@@ -50,10 +51,11 @@ private KeyStoreFactory() {
5051
static KeyStore create(Path certPath, Path keyPath, String alias) {
5152
try {
5253
KeyStore keyStore = getKeyStore();
53-
X509Certificate[] certificates = CertificateParser.parse(certPath);
54+
String certificateText = Files.readString(certPath);
55+
List<X509Certificate> certificates = PemCertificateParser.parse(certificateText);
5456
PrivateKey privateKey = getPrivateKey(keyPath);
5557
try {
56-
addCertificates(keyStore, certificates, privateKey, alias);
58+
addCertificates(keyStore, certificates.toArray(X509Certificate[]::new), privateKey, alias);
5759
}
5860
catch (KeyStoreException ex) {
5961
throw new IllegalStateException("Error adding certificates to KeyStore: " + ex.getMessage(), ex);
@@ -72,9 +74,10 @@ private static KeyStore getKeyStore()
7274
return keyStore;
7375
}
7476

75-
private static PrivateKey getPrivateKey(Path path) {
77+
private static PrivateKey getPrivateKey(Path path) throws IOException {
7678
if (path != null && Files.exists(path)) {
77-
return PrivateKeyParser.parse(path);
79+
String text = Files.readString(path);
80+
return PemPrivateKeyParser.parse(text);
7881
}
7982
return null;
8083
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,9 +17,6 @@
1717
package org.springframework.boot.buildpack.platform.docker.ssl;
1818

1919
import java.io.ByteArrayInputStream;
20-
import java.io.IOException;
21-
import java.nio.file.Files;
22-
import java.nio.file.Path;
2320
import java.security.cert.CertificateException;
2421
import java.security.cert.CertificateFactory;
2522
import java.security.cert.X509Certificate;
@@ -30,13 +27,16 @@
3027
import java.util.regex.Matcher;
3128
import java.util.regex.Pattern;
3229

30+
import org.springframework.util.Assert;
31+
import org.springframework.util.CollectionUtils;
32+
3333
/**
3434
* Parser for X.509 certificates in PEM format.
3535
*
3636
* @author Scott Frederick
3737
* @author Phillip Webb
3838
*/
39-
final class CertificateParser {
39+
final class PemCertificateParser {
4040

4141
private static final String HEADER = "-+BEGIN\\s+.*CERTIFICATE[^-]*-+(?:\\s|\\r|\\n)+";
4242

@@ -46,21 +46,23 @@ final class CertificateParser {
4646

4747
private static final Pattern PATTERN = Pattern.compile(HEADER + BASE64_TEXT + FOOTER, Pattern.CASE_INSENSITIVE);
4848

49-
private CertificateParser() {
49+
private PemCertificateParser() {
5050
}
5151

5252
/**
53-
* Load certificates from the specified file paths.
54-
* @param paths one or more paths to certificate files
55-
* @return certificates parsed from specified file paths
53+
* Parse certificates from the specified string.
54+
* @param text the text to parse
55+
* @return the parsed certificates
5656
*/
57-
static X509Certificate[] parse(Path... paths) {
58-
CertificateFactory factory = getCertificateFactory();
59-
List<X509Certificate> certificates = new ArrayList<>();
60-
for (Path path : paths) {
61-
readCertificates(path, factory, certificates::add);
57+
static List<X509Certificate> parse(String text) {
58+
if (text == null) {
59+
return null;
6260
}
63-
return certificates.toArray(new X509Certificate[0]);
61+
CertificateFactory factory = getCertificateFactory();
62+
List<X509Certificate> certs = new ArrayList<>();
63+
readCertificates(text, factory, certs::add);
64+
Assert.state(!CollectionUtils.isEmpty(certs), "Missing certificates or unrecognized format");
65+
return List.copyOf(certs);
6466
}
6567

6668
private static CertificateFactory getCertificateFactory() {
@@ -72,9 +74,8 @@ private static CertificateFactory getCertificateFactory() {
7274
}
7375
}
7476

75-
private static void readCertificates(Path path, CertificateFactory factory, Consumer<X509Certificate> consumer) {
77+
private static void readCertificates(String text, CertificateFactory factory, Consumer<X509Certificate> consumer) {
7678
try {
77-
String text = Files.readString(path);
7879
Matcher matcher = PATTERN.matcher(text);
7980
while (matcher.find()) {
8081
String encodedText = matcher.group(1);
@@ -85,8 +86,8 @@ private static void readCertificates(Path path, CertificateFactory factory, Cons
8586
}
8687
}
8788
}
88-
catch (CertificateException | IOException ex) {
89-
throw new IllegalStateException("Error reading certificate from '" + path + "' : " + ex.getMessage(), ex);
89+
catch (CertificateException ex) {
90+
throw new IllegalStateException("Error reading certificate: " + ex.getMessage(), ex);
9091
}
9192
}
9293

0 commit comments

Comments
 (0)