From b10948c50c734109112997199dddfcdf36e56c48 Mon Sep 17 00:00:00 2001
From: Wiktor Kwapisiewicz <wiktor@metacode.biz>
Date: Mon, 3 Mar 2025 09:29:23 +0100
Subject: [PATCH] fix(deps): update nethsm-sdk-rs to v2 and ureq to v3

Closes: https://gitlab.archlinux.org/archlinux/signstar/-/merge_requests/175
Closes: https://gitlab.archlinux.org/archlinux/signstar/-/merge_requests/160
Signed-off-by: Wiktor Kwapisiewicz <wiktor@metacode.biz>
---
 Cargo.lock               | 131 +++++++++++++++++++++++++++++++++++++--
 Cargo.toml               |   2 +-
 nethsm-tests/src/lib.rs  |   3 +-
 nethsm/Cargo.toml        |   2 +-
 nethsm/src/lib.rs        |  71 +++++----------------
 nethsm/src/nethsm_sdk.rs |  26 +++++---
 6 files changed, 164 insertions(+), 71 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 085a315e..dcd06c9e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -563,6 +563,35 @@ version = "0.10.0-rc.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "68ff6be19477a1bd5441f382916a89bc2a0b2c35db6d41e0f6e8538bf6d6463f"
 
+[[package]]
+name = "cookie"
+version = "0.18.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747"
+dependencies = [
+ "percent-encoding",
+ "time",
+ "version_check",
+]
+
+[[package]]
+name = "cookie_store"
+version = "0.21.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2eac901828f88a5241ee0600950ab981148a18f2f756900ffba1b125ca6a3ef9"
+dependencies = [
+ "cookie",
+ "document-features",
+ "idna",
+ "indexmap",
+ "log",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "time",
+ "url",
+]
+
 [[package]]
 name = "core-foundation"
 version = "0.9.4"
@@ -763,6 +792,15 @@ dependencies = [
  "zeroize",
 ]
 
+[[package]]
+name = "deranged"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
+dependencies = [
+ "powerfmt",
+]
+
 [[package]]
 name = "derive_builder"
 version = "0.20.2"
@@ -900,6 +938,15 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "document-features"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d"
+dependencies = [
+ "litrs",
+]
+
 [[package]]
 name = "dsa"
 version = "0.6.3"
@@ -1775,6 +1822,12 @@ version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
 
+[[package]]
+name = "litrs"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5"
+
 [[package]]
 name = "log"
 version = "0.4.22"
@@ -1966,11 +2019,12 @@ dependencies = [
 
 [[package]]
 name = "nethsm-sdk-rs"
-version = "1.1.1"
+version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ec2e59e6584323dc5c6c44de9a4192aaf0b00bbfbd825aac235d212ddcdefd7"
+checksum = "a2aeec8637e90a7481ad1ee6edb2ac4eef2ed9f86fd867a89f7782ee6d35a287"
 dependencies = [
  "base64 0.21.7",
+ "http",
  "mime",
  "multipart",
  "serde",
@@ -2043,6 +2097,12 @@ dependencies = [
  "zeroize",
 ]
 
+[[package]]
+name = "num-conv"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
+
 [[package]]
 name = "num-integer"
 version = "0.1.46"
@@ -2448,6 +2508,12 @@ dependencies = [
  "universal-hash",
 ]
 
+[[package]]
+name = "powerfmt"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
+
 [[package]]
 name = "ppv-lite86"
 version = "0.2.20"
@@ -3444,6 +3510,37 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "time"
+version = "0.3.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21"
+dependencies = [
+ "deranged",
+ "itoa",
+ "num-conv",
+ "powerfmt",
+ "serde",
+ "time-core",
+ "time-macros",
+]
+
+[[package]]
+name = "time-core"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
+
+[[package]]
+name = "time-macros"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de"
+dependencies = [
+ "num-conv",
+ "time-core",
+]
+
 [[package]]
 name = "tinystr"
 version = "0.7.6"
@@ -3674,22 +3771,38 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
 
 [[package]]
 name = "ureq"
-version = "2.12.1"
+version = "3.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d"
+checksum = "217751151c53226090391713e533d9a5e904ba2570dabaaace29032687589c3e"
 dependencies = [
  "base64 0.22.1",
+ "cc",
+ "cookie_store",
  "flate2",
  "log",
- "once_cell",
+ "percent-encoding",
  "rustls",
+ "rustls-pemfile",
  "rustls-pki-types",
  "serde",
  "serde_json",
- "url",
+ "ureq-proto",
+ "utf-8",
  "webpki-roots",
 ]
 
+[[package]]
+name = "ureq-proto"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64adb55464bad1ab1aa9229133d0d59d2f679180f4d15f0d9debe616f541f25e"
+dependencies = [
+ "base64 0.22.1",
+ "http",
+ "httparse",
+ "log",
+]
+
 [[package]]
 name = "url"
 version = "2.5.4"
@@ -3702,6 +3815,12 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "utf-8"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
+
 [[package]]
 name = "utf16_iter"
 version = "1.0.5"
diff --git a/Cargo.toml b/Cargo.toml
index 94dd3cb4..aa0e310c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -36,7 +36,7 @@ testdir = "0.9.3"
 testresult = "0.4.1"
 thiserror = "2.0.4"
 tokio = { version = "1.42.0", features = ["macros"] }
-ureq = "2.12.1"
+ureq = "3.0.0"
 uuid = { version = "1.11.0", features = ["v7"] }
 
 [workspace.package]
diff --git a/nethsm-tests/src/lib.rs b/nethsm-tests/src/lib.rs
index 3a29c269..e2461ceb 100644
--- a/nethsm-tests/src/lib.rs
+++ b/nethsm-tests/src/lib.rs
@@ -363,7 +363,8 @@ pub fn update_file() -> TestResult<PathBuf> {
     let file = download_dir.join(file_name);
 
     if !file.exists() {
-        let mut file_bytes = ureq::get(&update_link).call()?.into_reader();
+        let mut file_bytes = ureq::get(&update_link).call()?.into_body();
+        let mut file_bytes = file_bytes.as_reader();
         let mut file_writer = File::create(&file)?;
         std::io::copy(&mut file_bytes, &mut file_writer)?;
         assert!(file.exists());
diff --git a/nethsm/Cargo.toml b/nethsm/Cargo.toml
index 34db4c50..650d4eb0 100644
--- a/nethsm/Cargo.toml
+++ b/nethsm/Cargo.toml
@@ -21,7 +21,7 @@ hex = { version = "0.4.3", features = ["serde"] }
 log = "0.4.22"
 md-5 = "0.10.6"
 nethsm-backup.workspace = true
-nethsm-sdk-rs = "1.1.1"
+nethsm-sdk-rs = "2.0.0"
 p224 = { version = "0.13.2", features = ["pem", "pkcs8"] }
 p256 = { version = "0.13.2", features = ["pem", "pkcs8"] }
 p384 = { version = "0.13.0", features = ["pem", "pkcs8"] }
diff --git a/nethsm/src/lib.rs b/nethsm/src/lib.rs
index e423d292..85d43e2e 100644
--- a/nethsm/src/lib.rs
+++ b/nethsm/src/lib.rs
@@ -91,13 +91,12 @@ use std::fmt::Display;
 use std::io::Read;
 use std::net::Ipv4Addr;
 use std::str::FromStr;
-use std::sync::Arc;
 use std::thread::available_parallelism;
 use std::time::Duration;
 
 use base64ct::{Base64, Encoding};
 use chrono::{DateTime, Utc};
-use log::{debug, error, info};
+use log::{error, info};
 use md5::{Digest as _, Md5};
 use nethsm_sdk_rs::apis::configuration::Configuration;
 use nethsm_sdk_rs::apis::default_api::{
@@ -193,9 +192,7 @@ pub use nethsm_sdk_rs::models::{
     SystemUpdateData,
     UserData,
 };
-use nethsm_sdk_rs::ureq::{Agent, AgentBuilder};
-use rustls::client::ClientConfig;
-use rustls::crypto::{CryptoProvider, ring as tls_provider};
+use nethsm_sdk_rs::ureq::{Agent, tls::TlsConfig};
 use serde::{Deserialize, Serialize};
 use serde_json::Value;
 use sha1::Sha1;
@@ -239,10 +236,10 @@ pub use openpgp::{
 
 mod tls;
 pub use tls::{ConnectionSecurity, HostCertificateFingerprints};
-use tls::{DangerIgnoreVerifier, FingerprintVerifier};
 
 mod user;
 pub use key::KeyId;
+use ureq::tls::TlsProvider;
 pub use user::Error as UserError;
 use user::NamespaceSupport;
 pub use user::{Credentials, NamespaceId, Passphrase, UserId};
@@ -465,7 +462,7 @@ impl NetHsm {
     ///
     /// # Errors
     ///
-    /// Returns an [`Error`] if the rustls based [`ClientConfig`] can not be created.
+    /// Returns an [`Error`] if the client config can not be created.
     pub fn new(
         url: Url,
         connection_security: ConnectionSecurity,
@@ -474,54 +471,20 @@ impl NetHsm {
         timeout_seconds: Option<u64>,
     ) -> Result<Self, Error> {
         let tls_conf = {
-            let tls_conf = ClientConfig::builder_with_provider(Arc::new(CryptoProvider {
-                cipher_suites: tls_provider::ALL_CIPHER_SUITES.into(),
-                ..tls_provider::default_provider()
-            }))
-            .with_protocol_versions(rustls::DEFAULT_VERSIONS)?;
+            let tls_conf = TlsConfig::builder();
 
             match connection_security {
-                ConnectionSecurity::Unsafe => {
-                    let dangerous = tls_conf.dangerous();
-                    dangerous
-                        .with_custom_certificate_verifier(Arc::new(DangerIgnoreVerifier(
-                            tls_provider::default_provider(),
-                        )))
-                        .with_no_client_auth()
-                }
+                ConnectionSecurity::Unsafe => tls_conf.disable_verification(true),
                 ConnectionSecurity::Native => {
-                    let native_certs = rustls_native_certs::load_native_certs();
-                    if !native_certs.errors.is_empty() {
-                        return Err(Error::CertLoading(native_certs.errors));
-                    }
-                    let native_certs = native_certs.certs;
-
-                    let roots = {
-                        let mut roots = rustls::RootCertStore::empty();
-                        let (added, failed) = roots.add_parsable_certificates(native_certs);
-                        debug!(
-                            "Added {added} certificates and failed to parse {failed} certificates"
-                        );
-                        if added == 0 {
-                            error!("Added no native certificates");
-                            return Err(Error::NoSystemCertsAdded { failed });
-                        }
-                        roots
-                    };
-
-                    tls_conf.with_root_certificates(roots).with_no_client_auth()
+                    tls_conf.provider(TlsProvider::Rustls);
+                    todo!("this is a bit more complex");
                 }
-                ConnectionSecurity::Fingerprints(fingerprints) => {
-                    let dangerous = tls_conf.dangerous();
-                    dangerous
-                        .with_custom_certificate_verifier(Arc::new(FingerprintVerifier {
-                            fingerprints,
-                            provider: tls_provider::default_provider(),
-                        }))
-                        .with_no_client_auth()
+                ConnectionSecurity::Fingerprints(_fingerprints) => {
+                    todo!("don't know how to implement that now");
                 }
             }
-        };
+        }
+        .build();
 
         let agent = {
             let max_idle_connections = max_idle_connections
@@ -533,14 +496,14 @@ impl NetHsm {
                 max_idle_connections, timeout_seconds
             );
 
-            RefCell::new(
-                AgentBuilder::new()
-                    .tls_config(Arc::new(tls_conf))
+            RefCell::new(Agent::new_with_config(
+                Agent::config_builder()
+                    .tls_config(tls_conf)
                     .max_idle_connections(max_idle_connections)
                     .max_idle_connections_per_host(max_idle_connections)
-                    .timeout_connect(Duration::from_secs(timeout_seconds))
+                    .timeout_connect(Some(Duration::from_secs(timeout_seconds)))
                     .build(),
-            )
+            ))
         };
 
         let (current_credentials, credentials) = if let Some(credentials) = credentials {
diff --git a/nethsm/src/nethsm_sdk.rs b/nethsm/src/nethsm_sdk.rs
index 1721c150..a7364c86 100644
--- a/nethsm/src/nethsm_sdk.rs
+++ b/nethsm/src/nethsm_sdk.rs
@@ -1,8 +1,8 @@
 use std::fmt::Display;
 
 use nethsm_sdk_rs::models::{SignMode, Switch, UnattendedBootConfig};
+use nethsm_sdk_rs::ureq::{Body, http::response::Response};
 use serde::{Deserialize, Serialize};
-use ureq::Response;
 
 /// A representation of a message body in an HTTP response
 ///
@@ -13,9 +13,9 @@ pub struct Message {
     message: String,
 }
 
-impl From<Response> for Message {
-    fn from(value: Response) -> Self {
-        if let Ok(message) = value.into_json() {
+impl From<Response<Body>> for Message {
+    fn from(mut value: Response<Body>) -> Self {
+        if let Ok(message) = value.body_mut().read_json() {
             message
         } else {
             Message {
@@ -68,13 +68,23 @@ impl<T> From<nethsm_sdk_rs::apis::Error<T>> for NetHsmApiError<T> {
     fn from(value: nethsm_sdk_rs::apis::Error<T>) -> Self {
         match value {
             nethsm_sdk_rs::apis::Error::Ureq(error) => match error {
-                nethsm_sdk_rs::ureq::Error::Status(code, response) => Self {
+                nethsm_sdk_rs::ureq::Error::StatusCode(code) => Self {
                     error: None,
-                    message: Some(ApiErrorMessage::from((code, response.into())).to_string()),
+                    message: Some(
+                        ApiErrorMessage::from((code, Message { message: "".into() })).to_string(),
+                    ),
                 },
-                nethsm_sdk_rs::ureq::Error::Transport(transport) => Self {
+                e => Self {
                     error: None,
-                    message: Some(format!("{}", transport)),
+                    message: Some(
+                        ApiErrorMessage::from((
+                            0,
+                            Message {
+                                message: e.to_string(),
+                            },
+                        ))
+                        .to_string(),
+                    ),
                 },
             },
             nethsm_sdk_rs::apis::Error::ResponseError(resp) => Self {
-- 
GitLab