feat(updater)!: add option to use insecure transport protocol (#1814)

pull/1841/head
Amr Bashir 8 months ago committed by GitHub
parent e564e2aa91
commit 04a0aea0ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
"updater": patch
---
**Breaking change**, Changed `UpdaterBuilder::endpoints` method to return a `Result`.

@ -0,0 +1,5 @@
---
"updater": patch
---
Add `dangerousInsecureTransportProtocol` config option to allow using insecure transport protocols, like `http`

@ -91,47 +91,69 @@ where
}
/// Updater configuration.
#[derive(Debug, Clone, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
#[derive(Debug, Clone, Default)]
pub struct Config {
/// Dangerously allow using insecure transport protocols for update endpoints.
pub dangerous_insecure_transport_protocol: bool,
/// Updater endpoints.
#[serde(default)]
pub endpoints: Vec<UpdaterEndpoint>,
pub endpoints: Vec<Url>,
/// Signature public key.
pub pubkey: String,
/// The Windows configuration for the updater.
pub windows: Option<WindowsConfig>,
}
/// A URL to an updater server.
///
/// The URL must use the `https` scheme on production.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct UpdaterEndpoint(pub Url);
impl std::fmt::Display for UpdaterEndpoint {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl<'de> Deserialize<'de> for UpdaterEndpoint {
impl<'de> Deserialize<'de> for Config {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let url = Url::deserialize(deserializer)?;
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Config {
#[serde(default, alias = "dangerous-insecure-transport-protocol")]
pub dangerous_insecure_transport_protocol: bool,
#[serde(default)]
pub endpoints: Vec<Url>,
pub pubkey: String,
pub windows: Option<WindowsConfig>,
}
let config = Config::deserialize(deserializer)?;
if url.scheme() != "https" {
validate_endpoints(
&config.endpoints,
config.dangerous_insecure_transport_protocol,
)
.map_err(serde::de::Error::custom)?;
Ok(Self {
dangerous_insecure_transport_protocol: config.dangerous_insecure_transport_protocol,
endpoints: config.endpoints,
pubkey: config.pubkey,
windows: config.windows,
})
}
}
pub(crate) fn validate_endpoints(
endpoints: &[Url],
dangerous_insecure_transport_protocol: bool,
) -> crate::Result<()> {
if !dangerous_insecure_transport_protocol {
for url in endpoints {
#[cfg(debug_assertions)]
#[cfg(debug_assertions)]
eprintln!("[\x1b[33mWARNING\x1b[0m] The configured updater endpoint doesn't use `https` protocol. This is allowed in development but will fail in release builds.");
eprintln!("[\x1b[33mWARNING\x1b[0m] The updater endpoint \"{url}\" doesn't use `https` protocol. This is allowed in development but will fail in release builds.");
#[cfg(debug_assertions)]
eprintln!("[\x1b[33mWARNING\x1b[0m] if this is a desired behavior, you can enable `dangerousInsecureTransportProtocol` in the plugin configuration");
#[cfg(not(debug_assertions))]
return Err(serde::de::Error::custom(
"The configured updater endpoint must use the `https` protocol.",
));
if url.scheme() != "https" {
return Err(crate::Error::InsecureTransportProtocol);
}
}
Ok(Self(url))
}
Ok(())
}

@ -71,6 +71,9 @@ pub enum Error {
InvalidHeaderValue(#[from] http::header::InvalidHeaderValue),
#[error(transparent)]
InvalidHeaderName(#[from] http::header::InvalidHeaderName),
/// The configured updater endpoint must use a secure protocol like `https`
#[error("The configured updater endpoint must use a secure protocol like `https`.")]
InsecureTransportProtocol,
#[error(transparent)]
Tauri(#[from] tauri::Error),
}

@ -148,9 +148,14 @@ impl UpdaterBuilder {
self
}
pub fn endpoints(mut self, endpoints: Vec<Url>) -> Self {
pub fn endpoints(mut self, endpoints: Vec<Url>) -> Result<Self> {
crate::config::validate_endpoints(
&endpoints,
self.config.dangerous_insecure_transport_protocol,
)?;
self.endpoints.replace(endpoints);
self
Ok(self)
}
pub fn executable_path<P: AsRef<Path>>(mut self, p: P) -> Self {
@ -219,7 +224,7 @@ impl UpdaterBuilder {
pub fn build(self) -> Result<Updater> {
let endpoints = self
.endpoints
.unwrap_or_else(|| self.config.endpoints.iter().map(|e| e.0.clone()).collect());
.unwrap_or_else(|| self.config.endpoints.clone());
if endpoints.is_empty() {
return Err(Error::EmptyEndpoints);

Loading…
Cancel
Save