Switch from staging to prod for version metadata
This commit is contained in:
parent
8fbf46194b
commit
200d4837f1
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@ -8,6 +8,7 @@
|
||||
|
||||
# Developer signing keys must be approved by team/tech leads
|
||||
/ci/keys/ @faern @raksooo @pinkisemils @albin-mullvad
|
||||
/mullvad-update/trusted-metadata-signing-pubkeys @faern @raksooo @pinkisemils @albin-mullvad
|
||||
|
||||
# Desktop build server files owned by desktop leads
|
||||
/ci/buildserver* @faern @raksooo
|
||||
|
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -2041,7 +2041,6 @@ dependencies = [
|
||||
"serde",
|
||||
"talpid-platform-metadata",
|
||||
"tokio",
|
||||
"vec1",
|
||||
"windows-sys 0.52.0",
|
||||
"winres",
|
||||
]
|
||||
@ -2496,7 +2495,6 @@ dependencies = [
|
||||
"sha2",
|
||||
"tokio",
|
||||
"toml 0.8.19",
|
||||
"vec1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2638,7 +2636,6 @@ dependencies = [
|
||||
"tokio-socks",
|
||||
"tower 0.5.1",
|
||||
"uuid",
|
||||
"vec1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -28,7 +28,6 @@ rand = { version = "0.8.5" }
|
||||
reqwest = { version = "0.12.9", default-features = false, features = ["rustls-tls"] }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
tokio = { workspace = true, features = ["rt-multi-thread", "fs"] }
|
||||
vec1 = { workspace = true }
|
||||
|
||||
talpid-platform-metadata = { path = "../talpid-platform-metadata" }
|
||||
mullvad-update = { path = "../mullvad-update", features = ["client"] }
|
||||
|
@ -19,17 +19,13 @@ use tokio::{
|
||||
sync::{mpsc, oneshot},
|
||||
task::JoinHandle,
|
||||
};
|
||||
use vec1::vec1;
|
||||
|
||||
/// ed25519 pubkey used to verify metadata from the Mullvad (stagemole) API
|
||||
const VERSION_PROVIDER_PUBKEY: &str = include_str!("../../mullvad-update/stagemole-pubkey");
|
||||
|
||||
/// Pinned root certificate used when fetching version metadata
|
||||
const PINNED_CERTIFICATE: &[u8] = include_bytes!("../../mullvad-api/le_root_cert.pem");
|
||||
|
||||
/// Base URL for pulling metadata. Actual JSON files should be stored at `<base
|
||||
/// url>/<platform>.json`
|
||||
const META_REPOSITORY_URL: &str = "https://api.stagemole.eu/app/releases/";
|
||||
const META_REPOSITORY_URL: &str = "https://api.mullvad.net/app/releases/";
|
||||
|
||||
/// Actions handled by an async worker task in [ActionMessageHandler].
|
||||
enum TaskMessage {
|
||||
@ -53,15 +49,11 @@ pub fn initialize_controller<T: AppDelegate + 'static>(delegate: &mut T, environ
|
||||
// Directory provider to use
|
||||
type DirProvider = crate::temp::TempDirProvider;
|
||||
|
||||
// Version info provider to use
|
||||
let verifying_key =
|
||||
mullvad_update::format::key::VerifyingKey::from_hex(VERSION_PROVIDER_PUBKEY)
|
||||
.expect("valid key");
|
||||
let cert = reqwest::Certificate::from_pem(PINNED_CERTIFICATE).expect("invalid cert");
|
||||
let version_provider = HttpVersionInfoProvider {
|
||||
url: get_metadata_url(),
|
||||
pinned_certificate: Some(cert),
|
||||
verifying_keys: vec1![verifying_key],
|
||||
verifying_keys: mullvad_update::keys::TRUSTED_METADATA_SIGNING_PUBKEYS.clone(),
|
||||
};
|
||||
|
||||
AppController::initialize::<_, Downloader<T>, _, DirProvider>(
|
||||
|
@ -47,7 +47,6 @@ tokio-rustls = { version = "0.26.0", features = [
|
||||
tokio-socks = "0.5.1"
|
||||
rustls-pemfile = "2.1.3"
|
||||
uuid = { version = "1.4.1", features = ["v4"] }
|
||||
vec1 = { workspace = true }
|
||||
|
||||
mullvad-encrypted-dns-proxy = { path = "../mullvad-encrypted-dns-proxy" }
|
||||
mullvad-fs = { path = "../mullvad-fs" }
|
||||
|
@ -4,7 +4,6 @@ use std::sync::Arc;
|
||||
use http::StatusCode;
|
||||
use mullvad_types::version::AppVersion;
|
||||
use mullvad_update::version::{VersionInfo, VersionParameters};
|
||||
use vec1::vec1;
|
||||
|
||||
use super::rest;
|
||||
use super::APP_URL_PREFIX;
|
||||
@ -23,9 +22,6 @@ pub struct AppVersionResponse {
|
||||
}
|
||||
|
||||
impl AppVersionProxy {
|
||||
/// Public key to use for `version_check_2` response
|
||||
const VERSION_PROVIDER_PUBKEY: &str = include_str!("../../mullvad-update/stagemole-pubkey");
|
||||
|
||||
/// Maximum size of `version_check_2` response
|
||||
const SIZE_LIMIT: usize = 1024 * 1024;
|
||||
|
||||
@ -65,18 +61,13 @@ impl AppVersionProxy {
|
||||
let path = format!("app/releases/{platform}.json");
|
||||
let request = self.handle.factory.get(&path);
|
||||
|
||||
let verifying_key =
|
||||
mullvad_update::format::key::VerifyingKey::from_hex(Self::VERSION_PROVIDER_PUBKEY)
|
||||
.expect("valid key");
|
||||
let verifying_keys = vec1![verifying_key];
|
||||
|
||||
async move {
|
||||
let request = request?.expected_status(&[StatusCode::OK]);
|
||||
let response = service.request(request).await?;
|
||||
let bytes = response.body_with_max_size(Self::SIZE_LIMIT).await?;
|
||||
|
||||
let response = mullvad_update::format::SignedResponse::deserialize_and_verify(
|
||||
&verifying_keys,
|
||||
&mullvad_update::keys::TRUSTED_METADATA_SIGNING_PUBKEYS,
|
||||
&bytes,
|
||||
lowest_metadata_version,
|
||||
)
|
||||
|
@ -22,7 +22,6 @@ serde = { workspace = true }
|
||||
sha2 = "0.10"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
toml = "0.8"
|
||||
vec1 = { workspace = true }
|
||||
|
||||
mullvad-version = { path = "../../mullvad-version", features = ["serde"] }
|
||||
mullvad-update = { path = "../", features = ["client", "sign"] }
|
||||
|
@ -28,9 +28,6 @@ const DEFAULT_ROLLOUT: f32 = 1.;
|
||||
/// Lowest version to accept using 'verify'
|
||||
const MIN_VERIFY_METADATA_VERSION: usize = 0;
|
||||
|
||||
/// Verification public key
|
||||
const VERIFYING_PUBKEY: &str = include_str!("../../stagemole-pubkey");
|
||||
|
||||
/// A tool that generates signed Mullvad version metadata.
|
||||
///
|
||||
/// Unsigned work is stored in `work/`, and signed work is stored in `signed/`
|
||||
|
@ -13,7 +13,6 @@ use std::{
|
||||
sync::LazyLock,
|
||||
};
|
||||
use tokio::{fs, io};
|
||||
use vec1::vec1;
|
||||
|
||||
use crate::{
|
||||
artifacts,
|
||||
@ -22,7 +21,7 @@ use crate::{
|
||||
|
||||
/// Base URL for metadata found with `meta pull`.
|
||||
/// Actual JSON files should be stored at `<base url>/<platform>.json`.
|
||||
const META_REPOSITORY_URL: &str = "https://releases.stagemole.eu/desktop/metadata/";
|
||||
const META_REPOSITORY_URL: &str = "https://releases.mullvad.net/desktop/metadata/";
|
||||
|
||||
/// TLS certificate to pin to for `meta pull`.
|
||||
static PINNED_CERTIFICATE: LazyLock<reqwest::Certificate> = LazyLock::new(|| {
|
||||
@ -128,14 +127,10 @@ impl Platform {
|
||||
|
||||
println!("Pulling {self} metadata from {url}...");
|
||||
|
||||
// Pull latest metadata
|
||||
let verifying_key =
|
||||
key::VerifyingKey::from_hex(crate::VERIFYING_PUBKEY).expect("Invalid pubkey");
|
||||
|
||||
let version_provider = HttpVersionInfoProvider {
|
||||
pinned_certificate: Some(PINNED_CERTIFICATE.clone()),
|
||||
url,
|
||||
verifying_keys: vec1![verifying_key],
|
||||
verifying_keys: mullvad_update::keys::TRUSTED_METADATA_SIGNING_PUBKEYS.clone(),
|
||||
};
|
||||
let response = version_provider
|
||||
.get_versions(crate::MIN_VERIFY_METADATA_VERSION)
|
||||
@ -236,11 +231,8 @@ impl Platform {
|
||||
println!("Verifying signature of {}...", signed_path.display());
|
||||
let bytes = fs::read(signed_path).await.context("Failed to read file")?;
|
||||
|
||||
let public_key = key::VerifyingKey::from_hex(include_str!("../../stagemole-pubkey"))
|
||||
.expect("Invalid pubkey");
|
||||
|
||||
format::SignedResponse::deserialize_and_verify(
|
||||
&vec1![public_key],
|
||||
&mullvad_update::keys::TRUSTED_METADATA_SIGNING_PUBKEYS,
|
||||
&bytes,
|
||||
crate::MIN_VERIFY_METADATA_VERSION,
|
||||
)
|
||||
|
@ -75,8 +75,7 @@ impl Serialize for SecretKey {
|
||||
}
|
||||
|
||||
/// ed25519 verifying key
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(Clone))]
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub struct VerifyingKey(pub ed25519_dalek::VerifyingKey);
|
||||
|
||||
impl fmt::Display for VerifyingKey {
|
||||
|
41
mullvad-update/src/keys.rs
Normal file
41
mullvad-update/src/keys.rs
Normal file
@ -0,0 +1,41 @@
|
||||
//! Keys that may be used for verifying data
|
||||
|
||||
use crate::format::key::VerifyingKey;
|
||||
use std::sync::LazyLock;
|
||||
use vec1::Vec1;
|
||||
|
||||
/// Pubkeys used to verify metadata from the Mullvad API (production)
|
||||
pub static TRUSTED_METADATA_SIGNING_PUBKEYS: LazyLock<Vec1<VerifyingKey>> =
|
||||
LazyLock::new(|| parse_keys(include_str!("../trusted-metadata-signing-pubkeys")));
|
||||
|
||||
fn parse_keys(keys: &str) -> Vec1<VerifyingKey> {
|
||||
let mut v = vec![];
|
||||
for key in keys.split('\n') {
|
||||
let key = key.trim();
|
||||
if key.starts_with('#') || key.is_empty() {
|
||||
continue;
|
||||
}
|
||||
v.push(VerifyingKey::from_hex(key).expect("invalid pubkey"));
|
||||
}
|
||||
v.try_into().expect("need at least one key")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[test]
|
||||
fn test_parse_keys() {
|
||||
let key1 = "AB4EF63FFDCC6BD5A19C30CD23B9DE03099407A04463418F17AE338B98AA09D4".to_lowercase();
|
||||
let key2 = "BB4EF63FFDCC6BD5A19C30CD23B9DE03099407A04463418F17AE338B98AA09D4".to_lowercase();
|
||||
let keys = parse_keys(&format!(
|
||||
r#"
|
||||
# test
|
||||
{key1}
|
||||
# test 2
|
||||
{key2}
|
||||
"#
|
||||
));
|
||||
assert_eq!(format!("{}", keys[0]), key1);
|
||||
assert_eq!(format!("{}", keys[1]), key2);
|
||||
|
||||
// Test that actual keys are validly parsed
|
||||
let _prod = &*TRUSTED_METADATA_SIGNING_PUBKEYS;
|
||||
}
|
@ -6,6 +6,8 @@ mod client;
|
||||
#[cfg(feature = "client")]
|
||||
pub use client::*;
|
||||
|
||||
pub mod keys;
|
||||
|
||||
pub mod version;
|
||||
|
||||
/// Parser and serializer for version metadata
|
||||
|
@ -1 +0,0 @@
|
||||
a0cd8f582e3147d57f7c01ec0fd306c8315290cea55725c7d5c76f835b78b363
|
8
mullvad-update/trusted-metadata-signing-pubkeys
Normal file
8
mullvad-update/trusted-metadata-signing-pubkeys
Normal file
@ -0,0 +1,8 @@
|
||||
# linus
|
||||
c99b5e6e76bb7ab5b6fc3cdfe146faaa8afcfce0326822fe1629e00e666988b4
|
||||
# oskar
|
||||
4f2faeeda078df4dc1eebfb217c475eec9635c65d8b075171c4cf1808356dde5
|
||||
# emils
|
||||
299e8b06355031781623de7c9a013eb88b07aee80476e2938ce01a7b623d29d0
|
||||
# albin
|
||||
af4f7762e3e13af87f2e8c8af8ce5cce456cd3390af6d881b1eb6f802786cc3f
|
1
test/Cargo.lock
generated
1
test/Cargo.lock
generated
@ -2101,7 +2101,6 @@ dependencies = [
|
||||
"tokio-socks",
|
||||
"tower 0.5.1",
|
||||
"uuid",
|
||||
"vec1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
Loading…
x
Reference in New Issue
Block a user