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

Insert a default allowlist during schema migrations #5700

Merged
merged 4 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
25 changes: 12 additions & 13 deletions dev-tools/omdb/src/bin/omdb/nexus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -890,23 +890,22 @@ fn print_task_details(bgtask: &BackgroundTask, details: &serde_json::Value) {
}
};
} else if name == "service_firewall_rule_propagation" {
#[derive(Deserialize)]
struct TaskSuccess {
/// Elapsed duration of the propagation
elapsed: std::time::Duration,
}

match serde_json::from_value::<TaskSuccess>(details.clone()) {
match serde_json::from_value::<serde_json::Value>(details.clone()) {
Ok(serde_json::Value::Object(map)) => {
if !map.is_empty() {
eprintln!(
" unexpected return value from task: {:?}",
map
)
}
}
Ok(val) => {
eprintln!(" unexpected return value from task: {:?}", val)
}
Err(error) => eprintln!(
"warning: failed to interpret task details: {:?}: {:?}",
error, details
),
Ok(success) => {
println!(
" successfully propagated rules in {:?}",
success.elapsed,
);
}
}
} else {
println!(
Expand Down
1 change: 0 additions & 1 deletion dev-tools/omdb/tests/successes.out
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,6 @@ task: "service_firewall_rule_propagation"
currently executing: no
last completed activation: <REDACTED ITERATIONS>, triggered by an explicit signal
started at <REDACTED TIMESTAMP> (<REDACTED DURATION>s ago) and ran for <REDACTED DURATION>ms
last completion reported error: Object (of type ById(..........<REDACTED_UUID>...........)) not found: allow-list

task: "service_zone_nat_tracker"
configured period: every 30s
Expand Down
3 changes: 2 additions & 1 deletion nexus/db-model/src/schema_versions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use std::collections::BTreeMap;
///
/// This must be updated when you change the database schema. Refer to
/// schema/crdb/README.adoc in the root of this repository for details.
pub const SCHEMA_VERSION: SemverVersion = SemverVersion::new(57, 0, 0);
pub const SCHEMA_VERSION: SemverVersion = SemverVersion::new(58, 0, 0);

/// List of all past database schema versions, in *reverse* order
///
Expand All @@ -29,6 +29,7 @@ static KNOWN_VERSIONS: Lazy<Vec<KnownVersion>> = Lazy::new(|| {
// | leaving the first copy as an example for the next person.
// v
// KnownVersion::new(next_int, "unique-dirname-with-the-sql-files"),
KnownVersion::new(58, "insert-default-allowlist"),
KnownVersion::new(57, "add-allowed-source-ips"),
KnownVersion::new(56, "bgp-oxpop-features"),
KnownVersion::new(55, "add-lookup-sled-by-policy-and-state-index"),
Expand Down
22 changes: 7 additions & 15 deletions nexus/db-queries/src/db/datastore/allow_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,7 @@ mod tests {
fixed_data::allow_list::USER_FACING_SERVICES_ALLOW_LIST_ID,
};
use nexus_test_utils::db::test_setup_database;
use omicron_common::api::external::{
self, Error, LookupType, ResourceType,
};
use omicron_common::api::external;
use omicron_test_utils::dev;

#[tokio::test]
Expand All @@ -99,20 +97,14 @@ mod tests {
let mut db = test_setup_database(&logctx.log).await;
let (opctx, datastore) = datastore_test(&logctx, &db).await;

// There should be nothing to begin with.
let result = datastore
// Should have the default to start with.
let record = datastore
.allow_list_view(&opctx)
.await
.expect_err("Expected query to fail when there are no records");
assert_eq!(
result,
Error::ObjectNotFound {
type_name: ResourceType::AllowList,
lookup_type: LookupType::ById(
USER_FACING_SERVICES_ALLOW_LIST_ID
)
},
"Expected an ObjectNotFound error when there is no IP allowlist"
.expect("Expected default data populated in dbinit.sql");
assert!(
record.allowed_ips.is_none(),
"Expected default ANY allowlist, represented as NULL in the DB"
);

// Upsert an allowlist, with some specific IPs.
Expand Down
10 changes: 8 additions & 2 deletions nexus/src/app/background/service_firewall_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,14 @@ impl BackgroundTask for ServiceRulePropagator {
);
serde_json::json!({"error" : e.to_string()})
} else {
debug!(log, "successfully propagated service firewall rules");
serde_json::json!({"elapsed": start.elapsed()})
// No meaningful data to return, the duration is already
// captured by the driver itself.
debug!(
log,
"successfully propagated service firewall rules";
"elapsed" => ?start.elapsed()
);
serde_json::json!({})
}
}
.boxed()
Expand Down
15 changes: 14 additions & 1 deletion schema/crdb/dbinit.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3818,6 +3818,19 @@ CREATE TABLE IF NOT EXISTS omicron.public.allow_list (
allowed_ips INET[] CHECK (array_length(allowed_ips, 1) > 0)
);

-- Insert default allowlist, allowing all traffic.
-- See `schema/crdb/insert-default-allowlist/up.sql` for details.
INSERT INTO omicron.public.allow_list (id, time_created, time_modified, allowed_ips)
VALUES (
'001de000-a110-4000-8000-000000000000',
NOW(),
NOW(),
NULL
)
ON CONFLICT (id)
DO NOTHING;


/*
* Keep this at the end of file so that the database does not contain a version
* until it is fully populated.
Expand All @@ -3829,7 +3842,7 @@ INSERT INTO omicron.public.db_metadata (
version,
target_version
) VALUES
(TRUE, NOW(), NOW(), '57.0.0', NULL)
(TRUE, NOW(), NOW(), '58.0.0', NULL)
ON CONFLICT DO NOTHING;

COMMIT;
23 changes: 23 additions & 0 deletions schema/crdb/insert-default-allowlist/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
-- This is a one-time insertion of the default allowlist for user-facing
-- services on existing racks.
--
-- During RSS, this row is populated by the bootstrap agent. Nexus awaits its
-- presence before launching its external server, to ensure the list is active
-- from the first request Nexus serves.
--
-- However, on existing racks, this row doesn't exist, and RSS also doesn't run.
-- Thus Nexus waits forever. Insert the default now, ignoring any conflict with
-- an existing row.
INSERT INTO omicron.public.allow_list (id, time_created, time_modified, allowed_ips)
VALUES (
-- Hardcoded ID, see nexus/db-queries/src/db/fixed_data/allow_list.rs.
'001de000-a110-4000-8000-000000000000',
NOW(),
NOW(),
-- No allowlist at all, meaning allow any external traffic.
NULL
)
-- If the row already exists, RSS has already run and the bootstrap agent has
-- inserted this record. Do not overwrite it.
ON CONFLICT (id)
DO NOTHING;
Loading