- Notifications
You must be signed in to change notification settings - Fork 2k
Closed
Description
I've noticed this when creating a secret with .dockerconfigjson set to an array of bytes that is base64 encoded to a string that contains an equals character. The result is '\u003d' is inserted in to the request body which then results in an error as Kubernetes cannot parse the invalid base64 characters.
It seems to occur in the JSON class which uses Gson to encode the data, but the Gson htmlSafe if true by default, so the characters are escaped.
This demonstrates the issue:
package comp3200.am3g15.forestgrowthsrc.k8s.client; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.TypeAdapter; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; import io.kubernetes.client.JSON; import io.kubernetes.client.models.V1Secret; import okio.ByteString; import java.io.IOException; import java.util.HashMap; import java.util.Map; public class Base64Test { public static void main(String[] args) { V1Secret secret = new V1Secret(); Map<String, byte[]> secretData = new HashMap<>(); secretData.put(".dockerconfigjson", new String("{\"auths\":{\"server\":{\"username\":\"username\",\"password\":\"password\",\"email\":\"email\",\"auth\":\"authhh\"}}}").getBytes()); secret.setData(secretData); //What occurs when CoreV1Api.createNamespacedSecret() is called JSON json = new JSON(); String erroneous = json.serialize(secret); //The Equivalent without the JSON class Gson gson = new GsonBuilder().registerTypeAdapter(byte[].class, new ByteArrayAdapter()).create(); String stillErroneous = gson.toJson(secret); //With HTML Safety Turned Off gson = new GsonBuilder().disableHtmlEscaping().registerTypeAdapter(byte[].class, new ByteArrayAdapter()).create(); String correct = gson.toJson(secret); System.out.printf("Bad: %s\nBad: %s\nCorrect: %s", erroneous, stillErroneous, correct); } //Pulled from the JSON class public static class ByteArrayAdapter extends TypeAdapter<byte[]> { public ByteArrayAdapter() { } public void write(JsonWriter out, byte[] value) throws IOException { if (value == null) { out.nullValue(); } else { out.value(ByteString.of(value).base64()); } } public byte[] read(JsonReader in) throws IOException { switch(in.peek()) { case NULL: in.nextNull(); return null; default: String bytesAsBase64 = in.nextString(); ByteString byteString = ByteString.decodeBase64(bytesAsBase64); return byteString.toByteArray(); } } } }
The output of which is:
Bad: {"data":{".dockerconfigjson":"eyJhdXRocyI6eyJzZXJ2ZXIiOnsidXNlcm5hbWUiOiJ1c2VybmFtZSIsInBhc3N3b3JkIjoicGFzc3dvcmQiLCJlbWFpbCI6ImVtYWlsIiwiYXV0aCI6ImF1dGhoaCJ9fX0\u003d"}} Bad: {"data":{".dockerconfigjson":"eyJhdXRocyI6eyJzZXJ2ZXIiOnsidXNlcm5hbWUiOiJ1c2VybmFtZSIsInBhc3N3b3JkIjoicGFzc3dvcmQiLCJlbWFpbCI6ImVtYWlsIiwiYXV0aCI6ImF1dGhoaCJ9fX0\u003d"}} Correct: {"data":{".dockerconfigjson":"eyJhdXRocyI6eyJzZXJ2ZXIiOnsidXNlcm5hbWUiOiJ1c2VybmFtZSIsInBhc3N3b3JkIjoicGFzc3dvcmQiLCJlbWFpbCI6ImVtYWlsIiwiYXV0aCI6ImF1dGhoaCJ9fX0="}}
Notice the presence of \u003d
at the end of the first two strings.
Metadata
Metadata
Assignees
Labels
No labels