Skip to content

Commit

Permalink
Fix #3083: CertificateException due to PEM being decoded in CertUtils
Browse files Browse the repository at this point in the history
Use java.util.Base64 instead of okio.ByteString to decode base64 encoded
string since former one throws IllegalArgumentException in case input
string in invalid base64 encoded string.

okio.ByteString returns non-null value even for invalid base64 decoded
strings

Signed-off-by: Rohan Kumar <[email protected]>
  • Loading branch information
rohanKanojia authored and manusa committed Jul 5, 2021
1 parent b169f52 commit e580fe4
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### 5.6-SNAPSHOT

#### Bugs
* Fix #3083: CertificateException due to PEM being decoded in CertUtils

#### Improvements

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

import io.fabric8.kubernetes.client.KubernetesClientException;
import io.fabric8.kubernetes.client.utils.Utils;
import okio.ByteString;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
Expand Down Expand Up @@ -46,29 +45,23 @@
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.util.Base64;
import java.util.Collection;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;

public class CertUtils {
private CertUtils() { }

private static final Logger LOG = LoggerFactory.getLogger(CertUtils.class);
public static String TRUST_STORE_SYSTEM_PROPERTY = "javax.net.ssl.trustStore";
public static String TRUST_STORE_PASSWORD_SYSTEM_PROPERTY = "javax.net.ssl.trustStorePassword";
public static String KEY_STORE_SYSTEM_PROPERTY = "javax.net.ssl.keyStore";
public static String KEY_STORE_PASSWORD_SYSTEM_PROPERTY = "javax.net.ssl.keyStorePassword";
public static final String TRUST_STORE_SYSTEM_PROPERTY = "javax.net.ssl.trustStore";
public static final String TRUST_STORE_PASSWORD_SYSTEM_PROPERTY = "javax.net.ssl.trustStorePassword";
public static final String KEY_STORE_SYSTEM_PROPERTY = "javax.net.ssl.keyStore";
public static final String KEY_STORE_PASSWORD_SYSTEM_PROPERTY = "javax.net.ssl.keyStorePassword";

public static InputStream getInputStreamFromDataOrFile(String data, String file) throws IOException {
if (data != null) {
byte[] bytes = null;
ByteString decoded = ByteString.decodeBase64(data);
if (decoded != null) {
bytes = decoded.toByteArray();
} else {
bytes = data.getBytes();
}

return new ByteArrayInputStream(bytes);
return createInputStreamFromBase64EncodedString(data);
}
if (file != null) {
return new ByteArrayInputStream(new String(Files.readAllBytes(Paths.get(file))).trim().getBytes());
Expand Down Expand Up @@ -284,10 +277,21 @@ private static byte[] readBytes(BufferedReader reader, String endMarker) throws

while ((line = reader.readLine()) != null) {
if (line.indexOf(endMarker) != -1) {
return ByteString.decodeBase64(buf.toString()).toByteArray();
return Base64.getDecoder().decode(buf.toString());
}
buf.append(line.trim());
}
throw new IOException("PEM is invalid : No end marker");
}

private static ByteArrayInputStream createInputStreamFromBase64EncodedString(String data) {
byte[] bytes;
try {
bytes = Base64.getDecoder().decode(data);
} catch (IllegalArgumentException illegalArgumentException) {
bytes = data.getBytes();
}

return new ByteArrayInputStream(bytes);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,26 @@
import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.utils.IOHelpers;
import io.fabric8.kubernetes.client.utils.Utils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
import java.util.Objects;
import java.util.Properties;

import static org.junit.jupiter.api.Assertions.assertEquals;
Expand Down Expand Up @@ -150,6 +155,33 @@ public void testLoadKeyStoreFromFileUsingSystemProperties()
verifyFabric8InStore(trustStore);
}

@Test
void testGetInputStreamFromDataOrFileShouldNotDecodedPEMAgain() throws IOException {
// Given
File certFile = new File(Objects.requireNonNull(getClass().getResource("/ssl/valid-non-base64-encoded-cert.pem")).getFile());
String certData = new String(Files.readAllBytes(certFile.toPath()));

// When
InputStream inputStream = CertUtils.getInputStreamFromDataOrFile(certData, null);
String certDataReadFromInputStream = IOHelpers.readFully(inputStream);

// Then
assertEquals(certData, certDataReadFromInputStream);
}

@Test
void testGetInputStreamFromDataOrFileShouldDecodeBase64EncodedString() throws IOException {
// Given
String inputStr = "this is a test";
String base64EncodedStr = Base64.getEncoder().encodeToString(inputStr.getBytes());

// When
InputStream inputStream = CertUtils.getInputStreamFromDataOrFile(base64EncodedStr, null);
String certDataReadFromInputStream = IOHelpers.readFully(inputStream);

// Then
assertEquals(inputStr, certDataReadFromInputStream);
}

private void verifyFabric8InStore(KeyStore trustStore)
throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN CERTIFICATE-----
MIIE2jCCAsICCQD4ptRhuthO0DANBgkqhkiG9w0BAQsFADAvMQswCQYDVQQGEwJV
UzELMAkGA1UECAwCQ0ExEzARBgNVBAMMCk5vbi1VbmlxdWUwHhcNMTkwNzAzMjIw
MjM4WhcNMjQwNzAxMjIwMjM4WjAvMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0Ex
EzARBgNVBAMMCk5vbi1VbmlxdWUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
AoICAQCxkBiScuviETwrbhBIbrl1PaJJU0cICccTBmkSXdApX1teayhI6LfLy5oO
oO3jOUjn69TCASE5O3TdWdipbuDtAeqYPBCoCneVj6S0DFTzLL705GCgdYZAmixc
g+pjUXX3N6bMnPiq8TcAUUoJbkJ78vFm4lAY5mIxEt5D67bP7OJSrSrD6shqg4OQ
D/XCYRm/5DSHEfSS/rN0hk1Bi7nv82OmtaYiWLHmPm9AxA/cydnkUmtKy/bvcTD4
nHqO1RRUNrnlQ4GEeOCFi0Gkh+4PNTTwtcIpMjyMhpGMIQDq6ts7BIQ6cddlquG1
AS7Cv0kfi7E0PIWJODwy1z9XFlngXKmgFmLjkhA9Fu6LJ6Vs6hzIj+j9hoafJ2+M
smHDH+8WTId4k0KoOldvKRVmj6h05qDNkLFqRspz095FQB1HlijXVmKp9duBvp0X
xV2lAr4LdWRikLcR2lmDBRIgWKjRkcORmoZUJMqarbRtsqN54ovAz9ozWJwa4xJQ
2flIfd3MJbla2b6LZBPhYKIQqH4XtU0qlRRCDFIlnr2cqKNzSMkZYA3Hh6ADPfNa
/XBA3xWQG6ilYfqIBeZDRJzcsTvuUG8A31TNGNXeAmeYeskud2yLm4ON2C/+c2c8
pkfyT3NnqJ03E3ddyuJ0i5t0e7RQIyyhMEh74T8wlKuRfL+rIwIDAQABMA0GCSqG
SIb3DQEBCwUAA4ICAQBskNG1Dl6TpYoPZlym4hC9fLQxeOLzqzzEe5NmFce+kSzQ
8iESW5ZXAPDfBzz47IncgDdWepvf9inr+t3af/YUbz8CWxudIdblfRWzmWXfzwlu
iBJMW5Y1jGBpQCmaPeoXIe6MlCvsguTOL048EjqU73BHoO0KiAvrs6Bo/p+CBzqE
XlpwnupHYrNQot27nPCAeVxL0Qi7qRa+dFXFLVDeOgOl6kCINcc48nzeDbTA57Ya
eniqG9vYP3EYL49OEQVv2MalTps9D6UiLqh56e28FRjLBaFLrOBbCGufoXkFnE+T
PrVt5ldiwBwqFYdodv3Zv6NpK7xTHpPcCjLx3xSMFvgF0Jmp8QnvCUS633uGtagB
aHwcDXdT0XbXqQLwK5pftM5nDfSCMjjcr/A293orfbHPWu4cc0UaCLsNZBFKdMc6
xeBxp2xTi0j4c/+d/xIr2uO/TZPs9CkqUhGzLhLGS3k2XE/YpNxT74bhGADhDpjq
9KzJAcudOUjKAjpeLP236gkf8mdanabQOnI8NNbFN/Zi+lQafsE9pEwr5lTePMQM
UWvw7UeqCGZviiYzo3NHUJOy6HSxkNhNJ0H6bx81znmfIMNNnvQs0GKcFN7TTS7C
iljS6PbiKUIwTo2q/rS3hKZT9cmt1+K7t9freBoNhO5kPCmHL6eQkqXJy6abvQ==
-----END CERTIFICATE-----

0 comments on commit e580fe4

Please sign in to comment.