Kubernetes-client: ConfigBuilder.withClientKeyData() is broken in 3.1.8

Created on 17 Feb 2018  Â·  5Comments  Â·  Source: fabric8io/kubernetes-client

ConfigBuilder.withClientKeyData() is broken in 3.1.8.

withClientCertData and withCaCertData work just fine.

The following code snippit shows the problem and the workaround.

boolean useWorkaround = true;
if (useWorkaround) {
    File tempWorkaroundFile = null;
    try {
        tempWorkaroundFile = java.nio.file.Files.createTempFile("workaround", "tmp").toFile();
        Files.write(key, tempWorkaroundFile, Charsets.UTF_8);
        configBuilder = configBuilder.withClientCertFile(tempWorkaroundFile.getAbsolutePath());
    } finally {
        tempWorkaroundFile.delete();
    }
 } else {
    configBuilder = configBuilder.withClientKeyData(key);
}

The problem manifests as:

Caused by: java.io.IOException: PEM is invalid: no begin marker
    at io.fabric8.kubernetes.client.internal.CertUtils.decodePem(CertUtils.java:220)
    at io.fabric8.kubernetes.client.internal.CertUtils.createKeyStore(CertUtils.java:105)
    at io.fabric8.kubernetes.client.internal.CertUtils.createKeyStore(CertUtils.java:196)
    at io.fabric8.kubernetes.client.internal.SSLUtils.keyManagers(SSLUtils.java:127)
    at io.fabric8.kubernetes.client.internal.SSLUtils.keyManagers(SSLUtils.java:121)
    at io.fabric8.kubernetes.client.utils.HttpClientUtils.createHttpClient(HttpClientUtils.java:64)
    ... 38 more

ConfigBuilder appears to be auto-generated so it is not clear to me how to fix this.

Most helpful comment

Hi @if6was9,
I spend 1 day to reproduce problem as below:

create new client keypair and get private key

        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024, new SecureRandom());
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        PrivateKey k = keyPair.getPrivate();

Using Bouncycastle to get PEM format of privatekey:

        StringWriter privout = new StringWriter();
        JcaPEMWriter jcaPEMWriter = new JcaPEMWriter(privout);
        jcaPEMWriter.writeObject(keyPair.getPrivate());
        jcaPEMWriter.close();
        String privateKeyPem = privout.toString());

After that i add it to ConfigBuilder of Kubernetes client

        builder.withCaCertData(certificateAuthority.replace("-----BEGIN CERTIFICATE-----", "")
                .replace("-----END CERTIFICATE-----", "").replace("\n", ""));

        builder.withClientCertData(clientCertificateSigned.replace("-----BEGIN CERTIFICATE-----", "")
                .replace("-----END CERTIFICATE-----", "").replace("\n", ""));

        builder.withClientKeyData(privout.toString());

        Config kubeConfig = builder.build();
        KubernetesClient result = new DefaultKubernetesClient(kubeConfig);
        System.out.println("result " + result);

Sometime it'll print result io.fabric8.kubernetes.client.DefaultKubernetesClient@11392934
But sometime it'll throw a exception
io.fabric8.kubernetes.client.KubernetesClientException: An error has occurred.
at io.fabric8.kubernetes.client.KubernetesClientException.launderThrowable(KubernetesClientException.java:62)
at io.fabric8.kubernetes.client.KubernetesClientException.launderThrowable(KubernetesClientException.java:53)
at io.fabric8.kubernetes.client.utils.HttpClientUtils.createHttpClient(HttpClientUtils.java:167)
at io.fabric8.kubernetes.client.BaseClient.(BaseClient.java:55)
at io.fabric8.kubernetes.client.DefaultKubernetesClient.(DefaultKubernetesClient.java:125)
at com.ird.api.container.service.KubernetesClientServiceImpl.main(KubernetesClientServiceImpl.java:965)
Caused by: java.io.IOException: PEM is invalid: no begin marker
at io.fabric8.kubernetes.client.internal.CertUtils.decodePem(CertUtils.java:220)
at io.fabric8.kubernetes.client.internal.CertUtils.createKeyStore(CertUtils.java:105)
at io.fabric8.kubernetes.client.internal.CertUtils.createKeyStore(CertUtils.java:196)
at io.fabric8.kubernetes.client.internal.SSLUtils.keyManagers(SSLUtils.java:127)
at io.fabric8.kubernetes.client.internal.SSLUtils.keyManagers(SSLUtils.java:121)
at io.fabric8.kubernetes.client.utils.HttpClientUtils.createHttpClient(HttpClientUtils.java:64)
... 3 more

i investigate in
private static byte[] decodePem(InputStream keyInputStream) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(keyInputStream));
try {
String line;
while ((line = reader.readLine()) != null) {
if (line.contains("-----BEGIN ")) {
return readBytes(reader, line.trim().replace("BEGIN", "END"));
}
}
throw new IOException("PEM is invalid: no begin marker");
} finally {
reader.close();
}
}
when the problem occure, the first line in keyInputStream not is -----BEGIN RSA PRIVATE KEY-----, and the value is ��� �R.
Any suggestion to solve the problem.

I'll so pleased to hear from you.

All 5 comments

I have the same problem. Any help for me to fix this ?

It’s not a bug I learned with trial and error. Although it would make sense that the method would accept the contents of the file (which is already armored plaintext), it wants to see the key/cert data base64 encoded again.

I’ll submit a patch soon that gives a better exception if unexpected input is provided.

Thank you @if6was9 .

Hi @if6was9,
I spend 1 day to reproduce problem as below:

create new client keypair and get private key

        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024, new SecureRandom());
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        PrivateKey k = keyPair.getPrivate();

Using Bouncycastle to get PEM format of privatekey:

        StringWriter privout = new StringWriter();
        JcaPEMWriter jcaPEMWriter = new JcaPEMWriter(privout);
        jcaPEMWriter.writeObject(keyPair.getPrivate());
        jcaPEMWriter.close();
        String privateKeyPem = privout.toString());

After that i add it to ConfigBuilder of Kubernetes client

        builder.withCaCertData(certificateAuthority.replace("-----BEGIN CERTIFICATE-----", "")
                .replace("-----END CERTIFICATE-----", "").replace("\n", ""));

        builder.withClientCertData(clientCertificateSigned.replace("-----BEGIN CERTIFICATE-----", "")
                .replace("-----END CERTIFICATE-----", "").replace("\n", ""));

        builder.withClientKeyData(privout.toString());

        Config kubeConfig = builder.build();
        KubernetesClient result = new DefaultKubernetesClient(kubeConfig);
        System.out.println("result " + result);

Sometime it'll print result io.fabric8.kubernetes.client.DefaultKubernetesClient@11392934
But sometime it'll throw a exception
io.fabric8.kubernetes.client.KubernetesClientException: An error has occurred.
at io.fabric8.kubernetes.client.KubernetesClientException.launderThrowable(KubernetesClientException.java:62)
at io.fabric8.kubernetes.client.KubernetesClientException.launderThrowable(KubernetesClientException.java:53)
at io.fabric8.kubernetes.client.utils.HttpClientUtils.createHttpClient(HttpClientUtils.java:167)
at io.fabric8.kubernetes.client.BaseClient.(BaseClient.java:55)
at io.fabric8.kubernetes.client.DefaultKubernetesClient.(DefaultKubernetesClient.java:125)
at com.ird.api.container.service.KubernetesClientServiceImpl.main(KubernetesClientServiceImpl.java:965)
Caused by: java.io.IOException: PEM is invalid: no begin marker
at io.fabric8.kubernetes.client.internal.CertUtils.decodePem(CertUtils.java:220)
at io.fabric8.kubernetes.client.internal.CertUtils.createKeyStore(CertUtils.java:105)
at io.fabric8.kubernetes.client.internal.CertUtils.createKeyStore(CertUtils.java:196)
at io.fabric8.kubernetes.client.internal.SSLUtils.keyManagers(SSLUtils.java:127)
at io.fabric8.kubernetes.client.internal.SSLUtils.keyManagers(SSLUtils.java:121)
at io.fabric8.kubernetes.client.utils.HttpClientUtils.createHttpClient(HttpClientUtils.java:64)
... 3 more

i investigate in
private static byte[] decodePem(InputStream keyInputStream) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(keyInputStream));
try {
String line;
while ((line = reader.readLine()) != null) {
if (line.contains("-----BEGIN ")) {
return readBytes(reader, line.trim().replace("BEGIN", "END"));
}
}
throw new IOException("PEM is invalid: no begin marker");
} finally {
reader.close();
}
}
when the problem occure, the first line in keyInputStream not is -----BEGIN RSA PRIVATE KEY-----, and the value is ��� �R.
Any suggestion to solve the problem.

I'll so pleased to hear from you.

Was this page helpful?
0 / 5 - 0 ratings