-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WIP: Add a source IP allowlist for user-facing services
- Add database table and updates with an allowlist of IPs. This is currently structured as a table with one row, and an array of INETs as the allowlist. - Add Nexus API for viewing / updating allowlist. Also does basic sanity checks on the list, most importantly that the source IP the request came from is _on_ the list. - Add the allowlist to wicket example config file - Add the allowlist into the rack initialization request, and insert it into the database during Nexus's internal server handling of that request. - Read allowlist and convert to firewall rules when plumbing any service firewall rules to sled agents. - Add method for waiting on this plumbing _before_ starting Nexus's external server, to ensure the IP allowlist is set before anything can reach Nexus.
- Loading branch information
Showing
32 changed files
with
1,127 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this | ||
// file, You can obtain one at https://mozilla.org/MPL/5.0/. | ||
|
||
// Copyright 2024 Oxide Computer Company | ||
|
||
//! Database representation of allowed source IP address, for implementing basic | ||
//! IP allowlisting. | ||
use crate::schema::allowed_source_ip; | ||
use crate::Generation; | ||
use chrono::DateTime; | ||
use chrono::Utc; | ||
use ipnetwork::IpNetwork; | ||
use nexus_types::external_api::params; | ||
use nexus_types::external_api::views; | ||
use omicron_common::api::external; | ||
use omicron_common::api::external::IpNet; | ||
use serde::Deserialize; | ||
use serde::Serialize; | ||
use uuid::Uuid; | ||
|
||
/// Database model for an allowlist of source IP addresses. | ||
#[derive( | ||
Queryable, Insertable, Selectable, Clone, Debug, Serialize, Deserialize, | ||
)] | ||
#[diesel(table_name = allowed_source_ip)] | ||
pub struct AllowedSourceIp { | ||
pub id: Uuid, | ||
pub time_created: DateTime<Utc>, | ||
pub time_modified: DateTime<Utc>, | ||
pub generation: Generation, | ||
pub allowed_ips: Option<Vec<IpNetwork>>, | ||
} | ||
|
||
impl AllowedSourceIp { | ||
/// Construct a new allowlist record. | ||
pub fn new(id: Uuid, allowed_ips: external::AllowedSourceIps) -> Self { | ||
let now = Utc::now(); | ||
let allowed_ips = match allowed_ips { | ||
external::AllowedSourceIps::Any => None, | ||
external::AllowedSourceIps::List(list) => { | ||
Some(list.into_iter().map(Into::into).collect()) | ||
} | ||
}; | ||
Self { | ||
id, | ||
time_created: now, | ||
time_modified: now, | ||
generation: Generation::new(), | ||
allowed_ips, | ||
} | ||
} | ||
} | ||
|
||
#[derive(AsChangeset)] | ||
#[diesel(table_name = allowed_source_ip, treat_none_as_null = true)] | ||
pub struct AllowedSourceIpUpdate { | ||
/// The new list of allowed IPs. | ||
pub allowed_ips: Option<Vec<IpNetwork>>, | ||
} | ||
|
||
impl From<params::AllowedSourceIpsUpdate> for AllowedSourceIpUpdate { | ||
fn from(params: params::AllowedSourceIpsUpdate) -> Self { | ||
let allowed_ips = match params.allowed_ips { | ||
external::AllowedSourceIps::Any => None, | ||
external::AllowedSourceIps::List(list) => { | ||
Some(list.into_iter().map(Into::into).collect()) | ||
} | ||
}; | ||
Self { allowed_ips } | ||
} | ||
} | ||
|
||
impl From<AllowedSourceIp> for views::AllowedSourceIps { | ||
fn from(db: AllowedSourceIp) -> Self { | ||
let allowed_ips = if let Some(list) = db.allowed_ips { | ||
assert!( | ||
!list.is_empty(), | ||
"IP allowlist must not be empty, use NULL instead" | ||
); | ||
external::AllowedSourceIps::List( | ||
list.into_iter().map(IpNet::from).collect(), | ||
) | ||
} else { | ||
external::AllowedSourceIps::Any | ||
}; | ||
Self { | ||
time_created: db.time_created, | ||
time_modified: db.time_modified, | ||
allowed_ips, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.