From 6b48da8485ff79f481f42e0d91d793206b0f97e2 Mon Sep 17 00:00:00 2001 From: goenning Date: Sat, 30 Nov 2024 17:08:38 +0000 Subject: [PATCH 1/2] support for utf16 files Signed-off-by: goenning --- kube-client/src/config/file_config.rs | 33 ++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/kube-client/src/config/file_config.rs b/kube-client/src/config/file_config.rs index dd41cc5db..698ae2ca7 100644 --- a/kube-client/src/config/file_config.rs +++ b/kube-client/src/config/file_config.rs @@ -1,6 +1,6 @@ use std::{ collections::HashMap, - fs, + fs, io, path::{Path, PathBuf}, }; @@ -351,8 +351,8 @@ const KUBECONFIG: &str = "KUBECONFIG"; impl Kubeconfig { /// Read a Config from an arbitrary location pub fn read_from>(path: P) -> Result { - let data = fs::read_to_string(&path) - .map_err(|source| KubeconfigError::ReadConfig(source, path.as_ref().into()))?; + let data = + read_path(&path).map_err(|source| KubeconfigError::ReadConfig(source, path.as_ref().into()))?; // Remap all files we read to absolute paths. let mut merged_docs = None; @@ -497,6 +497,33 @@ where }); } +fn read_path>(path: P) -> io::Result { + let bytes = fs::read(&path)?; + match bytes.as_slice() { + [0xFF, 0xFE, ..] => { + let utf16_data: Vec = bytes[2..] + .chunks(2) + .map(|chunk| u16::from_le_bytes([chunk[0], chunk[1]])) + .collect(); + String::from_utf16(&utf16_data) + .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid UTF-16 LE")) + } + [0xFE, 0xFF, ..] => { + let utf16_data: Vec = bytes[2..] + .chunks(2) + .map(|chunk| u16::from_be_bytes([chunk[0], chunk[1]])) + .collect(); + String::from_utf16(&utf16_data) + .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid UTF-16 BE")) + } + [0xEF, 0xBB, 0xBF, ..] => String::from_utf8(bytes[3..].to_vec()) + .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid UTF-8 BOM")), + _ => { + String::from_utf8(bytes).map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid UTF-8")) + } + } +} + fn to_absolute(dir: &Path, file: &str) -> Option { let path = Path::new(&file); if path.is_relative() { From 37b5e394178357bd539467fd35e5ea2cc86f3a21 Mon Sep 17 00:00:00 2001 From: goenning Date: Thu, 5 Dec 2024 18:10:10 +0000 Subject: [PATCH 2/2] add test cases for utf16 Signed-off-by: goenning --- kube-client/src/config/file_config.rs | 17 ++++++++++++++++ .../config/test_data/kubeconfig_utf16be.yaml | Bin 0 -> 810 bytes .../config/test_data/kubeconfig_utf16le.yaml | Bin 0 -> 810 bytes .../src/config/test_data/kubeconfig_utf8.yaml | 19 ++++++++++++++++++ 4 files changed, 36 insertions(+) create mode 100644 kube-client/src/config/test_data/kubeconfig_utf16be.yaml create mode 100644 kube-client/src/config/test_data/kubeconfig_utf16le.yaml create mode 100644 kube-client/src/config/test_data/kubeconfig_utf8.yaml diff --git a/kube-client/src/config/file_config.rs b/kube-client/src/config/file_config.rs index 698ae2ca7..c290289d5 100644 --- a/kube-client/src/config/file_config.rs +++ b/kube-client/src/config/file_config.rs @@ -996,4 +996,21 @@ users: json!({"audience": "foo", "other": "bar"}) ); } + + #[tokio::test] + async fn parse_kubeconfig_encodings() { + let files = vec![ + "kubeconfig_utf8.yaml", + "kubeconfig_utf16le.yaml", + "kubeconfig_utf16be.yaml", + ]; + + for file_name in files { + let path = PathBuf::from(format!("{}/src/config/test_data/{}", env!("CARGO_MANIFEST_DIR"), file_name)); + let cfg = Kubeconfig::read_from(path).unwrap(); + assert_eq!(cfg.clusters[0].name, "k3d-promstack"); + assert_eq!(cfg.contexts[0].name, "k3d-promstack"); + assert_eq!(cfg.auth_infos[0].name, "admin@k3d-k3s-default"); + } + } } diff --git a/kube-client/src/config/test_data/kubeconfig_utf16be.yaml b/kube-client/src/config/test_data/kubeconfig_utf16be.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1788dc1cdefae27922ad277a07c9e4e0e40ef35c GIT binary patch literal 810 zcma))&rX9t7{ur7Q}6=#CmLfonRxKv-TMmFHng+>+GvcguKs3)0BYK11G|~sZ+2$B z{rpnUMhiV^rdkcFwJK#ww9|!7lxwLic-!q~U@5y(+-TB`Jf3V}dgjaFcWuhNWi^Mt z25a*9?+dy|MWZL?8$FB|o5;9}e=D0)-J-go?u>D+)6tjdT33wAj-ld?6}7G` zK@0BPpkWPaUjdCJXY=UXT3FYw@0QgXAKzx_V0w|++hR|(hQcafv8W(*3Z i9opaLGUi>x{O@AV{Z3!->sR3f?8n@8<`fgX>*E{U?1$w5 literal 0 HcmV?d00001 diff --git a/kube-client/src/config/test_data/kubeconfig_utf16le.yaml b/kube-client/src/config/test_data/kubeconfig_utf16le.yaml new file mode 100644 index 0000000000000000000000000000000000000000..edcbc6530055aaf17a14697760b45ec1f7686495 GIT binary patch literal 810 zcma)4OK!q26r6QWkqe|y6;&v!N-VnQzI)f{n4R$}YfZ#*CW zoE)}T;saAu2wZJYB13{bp6~#V6?UxG&3?vO%H4il)ub8TPS!-4@$+!jn{wW9wIF`Q zdW{2da@%!wpTiqj1blKH^ChNey0ml%JoiD=+MjX!#LdiSU>{VyM zYR-GNe9(RmcJ95w?`c#RNxu;}>J&hvfhO literal 0 HcmV?d00001 diff --git a/kube-client/src/config/test_data/kubeconfig_utf8.yaml b/kube-client/src/config/test_data/kubeconfig_utf8.yaml new file mode 100644 index 000000000..20879b3a4 --- /dev/null +++ b/kube-client/src/config/test_data/kubeconfig_utf8.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +clusters: +- cluster: + certificate-authority-data: aGVsbG8K + server: https://0.0.0.0:6443 + name: k3d-promstack +contexts: +- context: + cluster: k3d-promstack + user: admin@k3d-promstack + name: k3d-promstack +users: +- name: admin@k3d-k3s-default + user: + client-certificate-data: aGVsbG8K + client-key-data: aGVsbG8K +current-context: k3d-promstack +kind: Config +preferences: {} \ No newline at end of file