Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v2] TUF integration in Nexus + update artifact fetching by sled-agent #717

Merged
merged 49 commits into from
Mar 4, 2022
Merged
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
fc70559
WIP Nexus download endpoint
smklein Nov 22, 2021
80250e1
WIP writing files
smklein Nov 23, 2021
3ac2ddb
Merge branch 'main' into update-file-server
smklein Nov 29, 2021
9357831
Merge branch 'main' into update-file-server
smklein Nov 29, 2021
67fa74c
free function now method
smklein Nov 30, 2021
d7728a1
Merge branch 'main' into update-file-server
smklein Nov 30, 2021
7900929
sorting out errs
smklein Nov 30, 2021
a3f8121
Merge branch 'main' into update-file-server
smklein Nov 30, 2021
fad83b5
Merge branch 'main' into update-file-server
smklein Dec 1, 2021
4523cbd
Add tests, fix bugs
smklein Dec 1, 2021
e82885c
I guess compiling code is better than the alternative
smklein Dec 1, 2021
dc5897a
I EXPECTORATEd that my JSON would be more up-to-date
smklein Dec 1, 2021
3e82573
initial work for using the tough client in nexus
iliana Nov 19, 2021
55de464
run tough client in tokio::task::spawn_blocking
iliana Nov 30, 2021
9eab4b8
allow an unconfigured updates system
iliana Nov 30, 2021
383d966
woo license header
iliana Dec 1, 2021
76a6bf9
fix hardcoded base URLs to use localhost, for now
iliana Dec 1, 2021
8ad7ad6
add smf/nexus/root.json to .gitignore
iliana Dec 1, 2021
aec3211
rename columns to make more sense at first glance
iliana Dec 1, 2021
9426256
keep table in sync with artifacts.json
iliana Dec 1, 2021
f65f1bb
make the tests happy
iliana Dec 1, 2021
c653a11
add /updates/refresh to oxapi_demo
iliana Dec 2, 2021
e68080f
fix examples/config-file.toml
iliana Dec 2, 2021
3f42295
test [updates] in config works
iliana Dec 2, 2021
0618d09
remove dead code
iliana Dec 2, 2021
62e54d0
.unwrap() on JoinError from spawn_blocking
iliana Dec 2, 2021
e2af470
Merge branch 'main' into update-file-server
smklein Dec 2, 2021
3c6bd7d
Merge remote-tracking branch 'origin/update-file-server' into nexus-u…
iliana Dec 2, 2021
1afe334
wire download_artifact up to the database
iliana Dec 3, 2021
405d1f8
tell all sleds to apply all updates
iliana Dec 3, 2021
52b5c29
fixup! wire download_artifact up to the database
iliana Dec 3, 2021
7766021
actually verify the target after download
iliana Dec 3, 2021
e22c736
Merge branch 'main' into update-file-server
smklein Dec 20, 2021
9116b07
Keep merging
smklein Dec 20, 2021
a5c357b
Merge remote-tracking branch 'origin/update-file-server' into updates…
iliana Jan 21, 2022
ec1f4d4
Merge remote-tracking branch 'origin/main' into updates-demo
iliana Jan 21, 2022
374ffc7
use ..UpdatedNoContent instead of ..Ok<()>
iliana Jan 21, 2022
a4866fd
Merge remote-tracking branch 'origin/main' into updates-demo
iliana Jan 27, 2022
391d7f2
end-to-end updates test
iliana Mar 1, 2022
57238b0
Merge remote-tracking branch 'origin/main' into updates-demo
iliana Mar 2, 2022
832cb95
move UpdateArtifactKind into common
iliana Mar 2, 2022
a1cb33f
use a single updates base URL
iliana Mar 2, 2022
5a62f58
clean up unnecessary ResourceType variants
iliana Mar 3, 2022
7d49637
refactor to require full artifact descriptions
iliana Mar 3, 2022
b483cf0
work around dropshot Response<Body> issue
iliana Mar 3, 2022
449d24a
undo this change
iliana Mar 3, 2022
eae1452
combine updates integ tests into one module
iliana Mar 3, 2022
6f5264d
remove errant fixme
iliana Mar 4, 2022
1b489dd
comment nit
iliana Mar 4, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ tools/clickhouse*
tools/cockroach*
clickhouse/
cockroachdb/
smf/nexus/root.json
119 changes: 119 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions common/src/api/internal/nexus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::api::external::{
ByteCount, DiskState, Generation, InstanceCpuCount, InstanceState,
};
use chrono::{DateTime, Utc};
use parse_display::Display;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::net::SocketAddr;
Expand Down Expand Up @@ -77,3 +78,22 @@ impl ProducerEndpoint {
format!("{}/{}", &self.base_route, &self.id)
}
}

/// Description of a single update artifact.
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)]
pub struct UpdateArtifact {
pub name: String,
pub version: i64,
pub kind: UpdateArtifactKind,
}

/// Kinds of update artifacts, as used by Nexus to determine what updates are available and by
/// sled-agent to determine how to apply an update when asked.
#[derive(
Clone, Copy, Debug, PartialEq, Display, Deserialize, Serialize, JsonSchema,
)]
#[display(style = "kebab-case")]
#[serde(rename_all = "kebab-case")]
pub enum UpdateArtifactKind {
Zone,
}
30 changes: 29 additions & 1 deletion common/src/sql/dbinit.sql
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ CREATE TABLE omicron.public.rack (
/* Identity metadata (asset) */
id UUID PRIMARY KEY,
time_created TIMESTAMPTZ NOT NULL,
time_modified TIMESTAMPTZ NOT NULL
time_modified TIMESTAMPTZ NOT NULL,

/* Used to configure the updates service URL */
tuf_base_url STRING(512)
);

/*
Expand Down Expand Up @@ -692,6 +695,31 @@ CREATE INDEX ON omicron.public.console_session (

/*******************************************************************/

CREATE TYPE omicron.public.update_artifact_kind AS ENUM (
'zone'
);

CREATE TABLE omicron.public.update_available_artifact (
name STRING(40) NOT NULL,
version INT NOT NULL,
kind omicron.public.update_artifact_kind NOT NULL,

/* the version of the targets.json role this came from */
targets_role_version INT NOT NULL,

/* when the metadata this artifact was cached from expires */
valid_until TIMESTAMPTZ NOT NULL,

/* data about the target from the targets.json role */
target_name STRING(512) NOT NULL,
target_sha256 STRING(64) NOT NULL,
target_length INT NOT NULL,

PRIMARY KEY (name, version, kind)
);

/*******************************************************************/

/*
* Identity and Access Management (IAM)
*
Expand Down
14 changes: 14 additions & 0 deletions nexus-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,20 @@ impl From<&omicron_common::api::internal::nexus::ProducerEndpoint>
}
}

impl From<omicron_common::api::internal::nexus::UpdateArtifactKind>
for types::UpdateArtifactKind
{
fn from(
s: omicron_common::api::internal::nexus::UpdateArtifactKind,
) -> Self {
use omicron_common::api::internal::nexus::UpdateArtifactKind;

match s {
UpdateArtifactKind::Zone => types::UpdateArtifactKind::Zone,
}
}
}

impl From<std::time::Duration> for types::Duration {
fn from(s: std::time::Duration) -> Self {
Self { secs: s.as_secs(), nanos: s.subsec_nanos() }
Expand Down
3 changes: 3 additions & 0 deletions nexus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,17 @@ pq-sys = "*"
rand = "0.8.5"
ref-cast = "1.0"
reqwest = { version = "0.11.8", features = [ "json" ] }
ring = "0.16"
serde_json = "1.0"
serde_urlencoded = "0.7.1"
serde_with = "1.12.0"
sled-agent-client = { path = "../sled-agent-client" }
slog-dtrace = "0.2"
structopt = "0.3"
tempfile = "3.3"
thiserror = "1.0"
toml = "0.5.6"
tough = { version = "0.12", features = [ "http" ] }
usdt = "0.3.1"

[dependencies.api_identity]
Expand Down
21 changes: 20 additions & 1 deletion nexus/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ pub struct ConsoleConfig {
pub session_absolute_timeout_minutes: u32,
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct UpdatesConfig {
/** Trusted root.json role for the TUF updates repository. */
pub trusted_root: PathBuf,
/** Default base URLs for the TUF repository. */
pub default_base_url: String,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it seems straightforward to me that we'll host a TUF repo somewhere, and set the value according to that (for default_base_url) but where would the root.json file come from?

I saw you added it to the .gitignore, but if we merge this PR and I want to actually set up a TUF repo + go through this workflow, where should I get this file from?

(If this is a step a developer must do manually, maybe we should add some docs?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is something I expect we'll add during CI. We might have a different root.json for test builds, for instance. (A generic root.json might work here, but how do you share that key, and how do you avoid shipping production builds with that role as the trusted root?)

}

/**
* Configuration for the timeseries database.
*/
Expand Down Expand Up @@ -70,6 +78,10 @@ pub struct Config {
pub authn: AuthnConfig,
/** Timeseries database configuration. */
pub timeseries_db: TimeseriesDbConfig,
/// Updates-related configuration. Updates APIs return 400 Bad Request when this is
/// unconfigured.
#[serde(default)]
Comment on lines +81 to +83
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, this seems like a decent tradeoff to not break folks doing development.

pub updates: Option<UpdatesConfig>,
}

#[derive(Debug)]
Expand Down Expand Up @@ -175,7 +187,7 @@ impl Config {
mod test {
use super::{
AuthnConfig, Config, ConsoleConfig, LoadError, LoadErrorKind,
SchemeName, TimeseriesDbConfig,
SchemeName, TimeseriesDbConfig, UpdatesConfig,
};
use crate::db;
use dropshot::ConfigDropshot;
Expand Down Expand Up @@ -306,6 +318,9 @@ mod test {
if_exists = "fail"
[timeseries_db]
address = "[::1]:8123"
[updates]
trusted_root = "/path/to/root.json"
default_base_url = "http://example.invalid/"
"##,
)
.unwrap();
Expand Down Expand Up @@ -346,6 +361,10 @@ mod test {
timeseries_db: TimeseriesDbConfig {
address: "[::1]:8123".parse().unwrap()
},
updates: Some(UpdatesConfig {
trusted_root: PathBuf::from("/path/to/root.json"),
default_base_url: "http://example.invalid/".into(),
}),
}
);

Expand Down
2 changes: 1 addition & 1 deletion nexus/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ impl ServerContext {
* underlying nexus as well.
*/
pub fn new(
rack_id: &Uuid,
rack_id: Uuid,
log: Logger,
pool: db::Pool,
config: &config::Config,
Expand Down
Loading