From 1fcbfb8371476c85727d1abcd0c0ad91b7518614 Mon Sep 17 00:00:00 2001 From: Rain Date: Tue, 18 Aug 2026 18:46:20 -0700 Subject: [PATCH] [spr] changes to main this commit is based on Created using spr 1.3.6-beta.1 [skip ci] --- Cargo.lock | 4 +- Cargo.toml | 2 +- clients/wicketd-client/src/lib.rs | 2 - openapi/wicketd.json | 275 ------------------ wicket/src/cli/rack_setup.rs | 31 +- wicketd-api/Cargo.toml | 1 - wicketd-api/src/lib.rs | 66 ----- wicketd-commission-types/versions/Cargo.toml | 1 + .../versions/src/initial/rack_setup.rs | 8 +- wicketd/Cargo.toml | 1 + wicketd/src/commission/http_entrypoints.rs | 4 +- wicketd/src/http_entrypoints.rs | 67 ----- wicketd/src/rss_config.rs | 29 +- wicketd/tests/integration_tests/commission.rs | 5 +- workspace-hack/Cargo.toml | 4 +- 15 files changed, 56 insertions(+), 444 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5df23e97b3a..43e8a5b7d0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17759,6 +17759,7 @@ dependencies = [ "wicketd-commission-client", "wicketd-commission-types", "wicketd-commission-types-versions", + "zeroize", ] [[package]] @@ -17769,7 +17770,6 @@ dependencies = [ "dropshot", "gateway-client", "omicron-common", - "omicron-passwords", "omicron-uuid-kinds", "omicron-workspace-hack", "schemars 0.8.22", @@ -17866,6 +17866,7 @@ dependencies = [ "thiserror 2.0.18", "toml 0.8.23", "uuid", + "zeroize", ] [[package]] @@ -18607,6 +18608,7 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" dependencies = [ + "serde", "zeroize_derive", ] diff --git a/Cargo.toml b/Cargo.toml index 4a0dde6330e..c3793d39d87 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -909,7 +909,7 @@ wicketd-commission-types-versions = { path = "wicketd-commission-types/versions" x509-cert = { version = "0.2.5", default-features = false } xshell = "0.2.7" zerocopy = "0.8.26" -zeroize = { version = "1.8.1", features = ["zeroize_derive", "std"] } +zeroize = { version = "1.8.1", features = ["zeroize_derive", "serde", "std"] } zfs-test-harness = { path = "sled-storage/zfs-test-harness" } zip = { version = "4.2.0", default-features = false, features = ["deflate","bzip2"] } zone = { version = "0.3.1", default-features = false, features = ["async"] } diff --git a/clients/wicketd-client/src/lib.rs b/clients/wicketd-client/src/lib.rs index 53ce2ecbd61..6a7a83cc7f2 100644 --- a/clients/wicketd-client/src/lib.rs +++ b/clients/wicketd-client/src/lib.rs @@ -39,7 +39,6 @@ progenitor::generate_api!( ArtifactId = wicket_common::artifact::ArtifactId, Baseboard = sled_hardware_types::Baseboard, BaseboardId = sled_hardware_types::BaseboardId, - BgpAuthKey = wicketd_commission_types_versions::latest::rack_setup::BgpAuthKey, BgpAuthKeyId = wicketd_commission_types_versions::latest::rack_setup::BgpAuthKeyId, BgpAuthKeyInfo = wicket_common::rack_setup::BgpAuthKeyInfo, BgpAuthKeyStatus = wicket_common::rack_setup::BgpAuthKeyStatus, @@ -47,7 +46,6 @@ progenitor::generate_api!( BgpPeerAuthKind = wicket_common::rack_setup::BgpPeerAuthKind, BgpPeerConfig = omicron_common::api::internal::shared::BgpPeerConfig, BootstrapSledDescription = wicket_common::rack_setup::BootstrapSledDescription, - CertificateUploadResponse = wicketd_commission_types_versions::latest::rack_setup::CertificateUploadResponse, ClearUpdateStateOptions = wicket_common::rack_update::ClearUpdateStateOptions, ClearUpdateStateResponse = wicketd_commission_types_versions::latest::update::ClearUpdateStateResponse, CurrentRssUserConfigInsensitive = wicket_common::rack_setup::CurrentRssUserConfigInsensitive, diff --git a/openapi/wicketd.json b/openapi/wicketd.json index c3a2e940d06..844d814d320 100644 --- a/openapi/wicketd.json +++ b/openapi/wicketd.json @@ -344,21 +344,6 @@ "$ref": "#/components/responses/Error" } } - }, - "delete": { - "summary": "Reset all RSS configuration to their default values.", - "operationId": "delete_rss_config", - "responses": { - "204": { - "description": "resource updated" - }, - "4XX": { - "$ref": "#/components/responses/Error" - }, - "5XX": { - "$ref": "#/components/responses/Error" - } - } } }, "/rack-setup/config/bgp/auth-key": { @@ -396,86 +381,6 @@ } } }, - "/rack-setup/config/bgp/auth-key/{key_id}": { - "put": { - "summary": "Set the BGP authentication key for a particular key ID.", - "operationId": "put_bgp_auth_key", - "parameters": [ - { - "in": "path", - "name": "key_id", - "required": true, - "schema": { - "$ref": "#/components/schemas/BgpAuthKeyId" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PutBgpAuthKeyBody" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "successful operation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PutBgpAuthKeyResponse" - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/Error" - }, - "5XX": { - "$ref": "#/components/responses/Error" - } - } - } - }, - "/rack-setup/config/key": { - "post": { - "summary": "Add the private key of an external certificate.", - "description": "This must be paired with its certificate. They may be posted in either order, but one cannot post two keys in a row (or two certs in a row).", - "operationId": "post_rss_config_key", - "requestBody": { - "content": { - "application/json": { - "schema": { - "title": "String", - "type": "string" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "successful operation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CertificateUploadResponse" - } - } - } - }, - "4XX": { - "$ref": "#/components/responses/Error" - }, - "5XX": { - "$ref": "#/components/responses/Error" - } - } - } - }, "/rack-setup/config/multirack": { "get": { "summary": "Get the current status of the multirack join configuration.", @@ -526,33 +431,6 @@ } } }, - "/rack-setup/config/recovery-user-password-hash": { - "put": { - "summary": "Update the RSS config recovery silo user password hash.", - "operationId": "put_rss_config_recovery_user_password_hash", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PutRssRecoveryUserPasswordHash" - } - } - }, - "required": true - }, - "responses": { - "204": { - "description": "resource updated" - }, - "4XX": { - "$ref": "#/components/responses/Error" - }, - "5XX": { - "$ref": "#/components/responses/Error" - } - } - } - }, "/reload-config": { "post": { "summary": "Instruct wicketd to reload its SMF config properties.", @@ -957,31 +835,6 @@ "serial_number" ] }, - "BgpAuthKey": { - "description": "Describes the actual authentication key to use with a BGP peer.\n\nCurrently, only TCP-MD5 authentication is supported.", - "oneOf": [ - { - "description": "TCP-MD5 authentication.", - "type": "object", - "properties": { - "key": { - "description": "The pre-shared key.", - "type": "string" - }, - "kind": { - "type": "string", - "enum": [ - "tcp_md5" - ] - } - }, - "required": [ - "key", - "kind" - ] - } - ] - }, "BgpAuthKeyId": { "description": "The key identifier for authentication to use with a BGP peer.", "allOf": [ @@ -1161,71 +1014,6 @@ "sleds" ] }, - "CertificateUploadResponse": { - "description": "The result of uploading half of a certificate/key pair.", - "oneOf": [ - { - "description": "The key has been uploaded, but we're waiting on its corresponding certificate chain.", - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "waiting_on_cert" - ] - } - }, - "required": [ - "status" - ] - }, - { - "description": "The cert chain has been uploaded, but we're waiting on its corresponding private key.", - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "waiting_on_key" - ] - } - }, - "required": [ - "status" - ] - }, - { - "description": "A cert chain and its key have been accepted.", - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "cert_key_accepted" - ] - } - }, - "required": [ - "status" - ] - }, - { - "description": "A cert chain and its key are valid, but have already been uploaded.", - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": [ - "cert_key_duplicate_ignored" - ] - } - }, - "required": [ - "status" - ] - } - ] - }, "ClearUpdateStateOptions": { "type": "object", "properties": { @@ -2521,11 +2309,6 @@ "minLength": 1, "maxLength": 63 }, - "NewPasswordHash": { - "title": "A password hash in PHC string format", - "description": "Password hashes must be in PHC (Password Hashing Competition) string format. Passwords must be hashed with Argon2id. Password hashes may be rejected if the parameters appear not to be secure enough.", - "type": "string" - }, "Oui": { "description": "An Organization Unique Identifier.", "type": "array", @@ -3355,39 +3138,6 @@ }, "type": "string" }, - "PutBgpAuthKeyBody": { - "type": "object", - "properties": { - "key": { - "$ref": "#/components/schemas/BgpAuthKey" - } - }, - "required": [ - "key" - ] - }, - "PutBgpAuthKeyResponse": { - "type": "object", - "properties": { - "status": { - "$ref": "#/components/schemas/SetBgpAuthKeyStatus" - } - }, - "required": [ - "status" - ] - }, - "PutRssRecoveryUserPasswordHash": { - "type": "object", - "properties": { - "hash": { - "$ref": "#/components/schemas/NewPasswordHash" - } - }, - "required": [ - "hash" - ] - }, "RackInitUuid": { "x-rust-type": { "crate": "omicron-uuid-kinds", @@ -4188,31 +3938,6 @@ "ranges" ] }, - "SetBgpAuthKeyStatus": { - "oneOf": [ - { - "description": "The key was accepted and replaced an old key.", - "type": "string", - "enum": [ - "replaced" - ] - }, - { - "description": "The key was accepted, and is the same as the existing key.", - "type": "string", - "enum": [ - "unchanged" - ] - }, - { - "description": "The key was accepted and is new.", - "type": "string", - "enum": [ - "added" - ] - } - ] - }, "Sff8636Datapath": { "description": "The datapath of an SFF-8636 module.\n\nThis describes the state of a single lane in an SFF module. It includes information about input and output signals, faults, and controls.", "type": "object", diff --git a/wicket/src/cli/rack_setup.rs b/wicket/src/cli/rack_setup.rs index caeb70567ce..d461658ec12 100644 --- a/wicket/src/cli/rack_setup.rs +++ b/wicket/src/cli/rack_setup.rs @@ -31,15 +31,15 @@ use wicket_common::rack_setup::BgpAuthKeyInfo; use wicket_common::rack_setup::BgpAuthKeyStatus; use wicket_common::rack_setup::DisplaySlice; use wicketd_client::types::GetBgpAuthKeyParams; -use wicketd_client::types::NewPasswordHash; -use wicketd_client::types::PutBgpAuthKeyBody; -use wicketd_client::types::PutRssRecoveryUserPasswordHash; -use wicketd_client::types::SetBgpAuthKeyStatus; use wicketd_commission_types::rack_setup::BgpAuthKey; use wicketd_commission_types::rack_setup::BgpAuthKeyId; use wicketd_commission_types::rack_setup::CertificatePem; use wicketd_commission_types::rack_setup::CertificateUploadResponse; +use wicketd_commission_types::rack_setup::NewPasswordHash; +use wicketd_commission_types::rack_setup::PrivateKeyPem; +use wicketd_commission_types::rack_setup::PutRecoveryUserPasswordHash; use wicketd_commission_types::rack_setup::PutRssUserConfigInsensitive; +use wicketd_commission_types::rack_setup::SetBgpAuthKeyStatus; use zeroize::Zeroizing; mod config_toml; @@ -133,7 +133,7 @@ impl SetupArgs { } SetupArgs::ResetConfig => { slog::info!(log, "instructing wicketd to reset config..."); - client + commission_client .delete_rss_config() .await .context("failed to clear config")?; @@ -144,16 +144,17 @@ impl SetupArgs { let hash = NewPasswordHash(hash.to_string()); slog::info!(log, "uploading password hash to wicketd..."); - client + commission_client .put_rss_config_recovery_user_password_hash( - &PutRssRecoveryUserPasswordHash { hash }, + &PutRecoveryUserPasswordHash { hash }, ) .await .context("failed to upload password hash to wicketd")?; slog::info!(log, "password set"); } SetupArgs::SetBgpAuthKey(args) => { - args.exec(&log, &client, global_opts).await?; + args.exec(&log, &client, &commission_client, global_opts) + .await?; } SetupArgs::UploadCert => { slog::info!(log, "reading cert from stdin..."); @@ -207,8 +208,8 @@ impl SetupArgs { .context("failed to read key from stdin")?; slog::info!(log, "uploading key to wicketd..."); - let result = client - .post_rss_config_key(&key) + let result = commission_client + .post_rss_config_key(&PrivateKeyPem(key)) .await .context("failed to upload key to wicketd")? .into_inner(); @@ -292,6 +293,7 @@ impl SetBgpAuthKeyArgs { self, log: &Logger, client: &wicketd_client::Client, + commission_client: &wicketd_commission_client::Client, global_opts: GlobalOpts, ) -> Result<()> { let mut styles = Styles::default(); @@ -401,12 +403,11 @@ impl SetBgpAuthKeyArgs { let key = read_bgp_md5_key(&prompt)?; let info = BgpAuthKeyInfo::for_key(&key) .to_string_styled(styles.bold); - let response = client - .put_bgp_auth_key(&key_id, &PutBgpAuthKeyBody { key }) + let status = commission_client + .put_bgp_auth_key(key_id, &key) .await - .context("failed to set BGP auth key")?; - - let status = response.into_inner().status; + .context("failed to set BGP auth key")? + .into_inner(); match status { SetBgpAuthKeyStatus::Added => { eprintln!( diff --git a/wicketd-api/Cargo.toml b/wicketd-api/Cargo.toml index fefc7af99ab..811b4625b9e 100644 --- a/wicketd-api/Cargo.toml +++ b/wicketd-api/Cargo.toml @@ -11,7 +11,6 @@ bootstrap-agent-lockstep-types.workspace = true dropshot.workspace = true gateway-client.workspace = true omicron-common.workspace = true -omicron-passwords.workspace = true omicron-uuid-kinds.workspace = true omicron-workspace-hack.workspace = true schemars.workspace = true diff --git a/wicketd-api/src/lib.rs b/wicketd-api/src/lib.rs index e8bba535105..3e7d5a7a6bd 100644 --- a/wicketd-api/src/lib.rs +++ b/wicketd-api/src/lib.rs @@ -31,10 +31,7 @@ use wicket_common::rack_update::AbortUpdateOptions; use wicket_common::rack_update::ClearUpdateStateOptions; use wicket_common::rack_update::StartUpdateOptions; use wicket_common::update_events::EventReport; -use wicketd_commission_types::rack_setup::BgpAuthKey; use wicketd_commission_types::rack_setup::BgpAuthKeyId; -use wicketd_commission_types::rack_setup::CertificateUploadResponse; -use wicketd_commission_types::rack_setup::SetBgpAuthKeyStatus; use wicketd_commission_types::update::ClearUpdateStateResponse; use wicketd_commission_types::update::UpdateTargets; @@ -83,19 +80,6 @@ pub trait WicketdApi { body: TypedBody, ) -> Result; - /// Add the private key of an external certificate. - /// - /// This must be paired with its certificate. They may be posted in either - /// order, but one cannot post two keys in a row (or two certs in a row). - #[endpoint { - method = POST, - path = "/rack-setup/config/key" - }] - async fn post_rss_config_key( - rqctx: RequestContext, - body: TypedBody, - ) -> Result, HttpError>; - // -- BGP authentication key management /// Return information about BGP authentication keys, including checking @@ -114,36 +98,6 @@ pub trait WicketdApi { params: TypedBody, ) -> Result, HttpError>; - /// Set the BGP authentication key for a particular key ID. - #[endpoint { - method = PUT, - path = "/rack-setup/config/bgp/auth-key/{key_id}" - }] - async fn put_bgp_auth_key( - rqctx: RequestContext, - params: Path, - body: TypedBody, - ) -> Result, HttpError>; - - /// Update the RSS config recovery silo user password hash. - #[endpoint { - method = PUT, - path = "/rack-setup/config/recovery-user-password-hash" - }] - async fn put_rss_config_recovery_user_password_hash( - rqctx: RequestContext, - body: TypedBody, - ) -> Result; - - /// Reset all RSS configuration to their default values. - #[endpoint { - method = DELETE, - path = "/rack-setup/config" - }] - async fn delete_rss_config( - rqctx: RequestContext, - ) -> Result; - /// Query current state of rack setup. #[endpoint { method = GET, @@ -342,26 +296,6 @@ pub struct GetBgpAuthKeyParams { pub check_valid: BTreeSet, } -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)] -pub struct PutBgpAuthKeyParams { - pub key_id: BgpAuthKeyId, -} - -#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Eq)] -pub struct PutBgpAuthKeyBody { - pub key: BgpAuthKey, -} - -#[derive(Clone, Debug, Serialize, JsonSchema, PartialEq)] -pub struct PutBgpAuthKeyResponse { - pub status: SetBgpAuthKeyStatus, -} - -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)] -pub struct PutRssRecoveryUserPasswordHash { - pub hash: omicron_passwords::NewPasswordHash, -} - #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)] pub struct GetInventoryParams { /// Refresh the state of these SPs from MGS prior to returning (instead of diff --git a/wicketd-commission-types/versions/Cargo.toml b/wicketd-commission-types/versions/Cargo.toml index b1328d0885a..90d9eb3bc55 100644 --- a/wicketd-commission-types/versions/Cargo.toml +++ b/wicketd-commission-types/versions/Cargo.toml @@ -22,6 +22,7 @@ sled-hardware-types.workspace = true slog-error-chain.workspace = true thiserror.workspace = true uuid.workspace = true +zeroize.workspace = true [dev-dependencies] gateway-types-versions = { workspace = true, features = ["testing"] } diff --git a/wicketd-commission-types/versions/src/initial/rack_setup.rs b/wicketd-commission-types/versions/src/initial/rack_setup.rs index f0efc9c446a..508993c9ed1 100644 --- a/wicketd-commission-types/versions/src/initial/rack_setup.rs +++ b/wicketd-commission-types/versions/src/initial/rack_setup.rs @@ -19,6 +19,7 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize, Serializer}; use slog_error_chain::InlineErrorChain; use uuid::Uuid; +use zeroize::Zeroizing; // Re-exports of pinned types from sled-agent-types-versions. pub use sled_agent_types_versions::v1::early_networking::{ @@ -653,7 +654,12 @@ pub struct CertificatePem(pub String); /// /// The key material is redacted from the `Debug` output. #[derive(Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] -pub struct PrivateKeyPem(pub String); +pub struct PrivateKeyPem( + // Zeroizing wipes the backing allocation on drop. Serialization and + // deserialization are transparent, so schemars(with = "String") is + // reasonable. + #[schemars(with = "String")] pub Zeroizing, +); impl fmt::Debug for PrivateKeyPem { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/wicketd/Cargo.toml b/wicketd/Cargo.toml index 30525bba07b..a1bb6dfa7d1 100644 --- a/wicketd/Cargo.toml +++ b/wicketd/Cargo.toml @@ -110,3 +110,4 @@ subprocess.workspace = true tar.workspace = true tokio = { workspace = true, features = ["test-util"] } wicket.workspace = true +zeroize.workspace = true diff --git a/wicketd/src/commission/http_entrypoints.rs b/wicketd/src/commission/http_entrypoints.rs index eb56519bb6c..4b911765a8a 100644 --- a/wicketd/src/commission/http_entrypoints.rs +++ b/wicketd/src/commission/http_entrypoints.rs @@ -368,7 +368,7 @@ impl WicketdCommissionApi for WicketdCommissionApiImpl { )?; let response = rss_config - .push_cert(body.into_inner().0) + .push_cert(body.into_inner()) .map_err(|err| HttpError::for_bad_request(None, err))?; Ok(HttpResponseOk(response)) @@ -386,7 +386,7 @@ impl WicketdCommissionApi for WicketdCommissionApiImpl { )?; let response = rss_config - .push_key(body.into_inner().0) + .push_key(body.into_inner()) .map_err(|err| HttpError::for_bad_request(None, err))?; Ok(HttpResponseOk(response)) diff --git a/wicketd/src/http_entrypoints.rs b/wicketd/src/http_entrypoints.rs index 3daa1ad2bb0..e85366e119b 100644 --- a/wicketd/src/http_entrypoints.rs +++ b/wicketd/src/http_entrypoints.rs @@ -38,7 +38,6 @@ use wicket_common::rack_setup::GetBgpAuthKeyInfoResponse; use wicket_common::rack_update::AbortUpdateOptions; use wicket_common::update_events::EventReport; use wicketd_api::*; -use wicketd_commission_types::rack_setup::CertificateUploadResponse; use wicketd_commission_types::update::ClearUpdateStateResponse; use crate::ServerContext; @@ -159,24 +158,6 @@ impl WicketdApi for WicketdApiImpl { Ok(HttpResponseUpdatedNoContent()) } - async fn post_rss_config_key( - rqctx: RequestContext, - body: TypedBody, - ) -> Result, HttpError> { - let ctx = rqctx.context(); - - let mut config = ctx.rss_or_multirack_join_config.lock().unwrap(); - let rss_config = config.rss_config_mut_or_conflict( - "cannot post private keys when not preparing for RSS", - )?; - - let response = rss_config - .push_key(body.into_inner()) - .map_err(|err| HttpError::for_bad_request(None, err))?; - - Ok(HttpResponseOk(response)) - } - async fn get_bgp_auth_key_info( rqctx: RequestContext, // A bit weird for a GET request to have a TypedBody, but there's no other @@ -195,54 +176,6 @@ impl WicketdApi for WicketdApiImpl { Ok(HttpResponseOk(GetBgpAuthKeyInfoResponse { data })) } - async fn put_bgp_auth_key( - rqctx: RequestContext, - params: Path, - body: TypedBody, - ) -> Result, HttpError> { - let ctx = rqctx.context(); - let params = params.into_inner(); - - let mut config = ctx.rss_or_multirack_join_config.lock().unwrap(); - let status = config - .set_bgp_auth_key(params.key_id, body.into_inner().key) - .map_err(|err| HttpError::for_bad_request(None, err.to_string()))?; - - Ok(HttpResponseOk(PutBgpAuthKeyResponse { status })) - } - - async fn put_rss_config_recovery_user_password_hash( - rqctx: RequestContext, - body: TypedBody, - ) -> Result { - let ctx = rqctx.context(); - - let mut config = ctx.rss_or_multirack_join_config.lock().unwrap(); - - let rss_config = config.rss_config_mut_or_conflict( - "cannot put recovery user password when not preparing for RSS", - )?; - - rss_config.set_recovery_user_password_hash(body.into_inner().hash); - - Ok(HttpResponseUpdatedNoContent()) - } - - async fn delete_rss_config( - rqctx: RequestContext, - ) -> Result { - let ctx = rqctx.context(); - - let mut config = ctx.rss_or_multirack_join_config.lock().unwrap(); - let rss_config = config.rss_config_mut_or_conflict( - "cannot delete RSS config when not preparing for RSS", - )?; - - *rss_config = Default::default(); - - Ok(HttpResponseUpdatedNoContent()) - } - async fn get_rack_setup_state( rqctx: RequestContext, ) -> Result, HttpError> { diff --git a/wicketd/src/rss_config.rs b/wicketd/src/rss_config.rs index a67cec7fcf1..ed67392e4f4 100644 --- a/wicketd/src/rss_config.rs +++ b/wicketd/src/rss_config.rs @@ -44,8 +44,10 @@ use wicket_common::rack_setup::GetBgpAuthKeyInfoResponse; use wicketd_api::CurrentRssUserConfig; use wicketd_api::CurrentRssUserConfigSensitive; use wicketd_commission_types::rack_setup::BgpAuthKey; +use wicketd_commission_types::rack_setup::CertificatePem; use wicketd_commission_types::rack_setup::CertificateUploadResponse; use wicketd_commission_types::rack_setup::ManualPortConfig; +use wicketd_commission_types::rack_setup::PrivateKeyPem; use wicketd_commission_types::rack_setup::PutRssUserConfigInsensitive; use wicketd_commission_types::rack_setup::UserSpecifiedRackNetworkConfig; use wicketd_commission_types::rack_setup::UserSpecifiedRouterPeerAddr; @@ -247,17 +249,17 @@ impl CurrentRssConfig { pub(crate) fn push_cert( &mut self, - cert: String, + cert: CertificatePem, ) -> Result { - self.partial_external_certificate.cert = Some(cert); + self.partial_external_certificate.cert = Some(cert.0); self.maybe_promote_external_certificate() } pub(crate) fn push_key( &mut self, - key: String, + key: PrivateKeyPem, ) -> Result { - self.partial_external_certificate.key = Some(key); + self.partial_external_certificate.key = Some(key.0.to_string()); self.maybe_promote_external_certificate() } @@ -685,6 +687,7 @@ mod tests { use wicket_common::rack_setup::BgpAuthKeyStatus; use wicketd_commission_types::rack_setup::BgpAuthKeyId; use wicketd_commission_types::rack_setup::SetBgpAuthKeyStatus; + use zeroize::Zeroizing; use super::*; @@ -1064,11 +1067,13 @@ mod tests { let mut config = CurrentRssConfig::default(); assert_eq!( - config.push_cert(cert.clone()).unwrap(), + config.push_cert(CertificatePem(cert.clone())).unwrap(), CertificateUploadResponse::WaitingOnKey, ); assert_eq!( - config.push_key(key.clone()).unwrap(), + config + .push_key(PrivateKeyPem(Zeroizing::new(key.clone()))) + .unwrap(), CertificateUploadResponse::CertKeyAccepted, ); assert_eq!(config.external_certificates.len(), 1); @@ -1076,11 +1081,13 @@ mod tests { // Re-uploading the same pair reports CertKeyDuplicateIgnored and adds // no second entry. assert_eq!( - config.push_cert(cert.clone()).unwrap(), + config.push_cert(CertificatePem(cert.clone())).unwrap(), CertificateUploadResponse::WaitingOnKey, ); assert_eq!( - config.push_key(key.clone()).unwrap(), + config + .push_key(PrivateKeyPem(Zeroizing::new(key.clone()))) + .unwrap(), CertificateUploadResponse::CertKeyDuplicateIgnored, ); assert_eq!(config.external_certificates.len(), 1); @@ -1093,11 +1100,13 @@ mod tests { let other_key = other.end_cert_private_key_as_pem(); assert_ne!(other_cert, cert); assert_eq!( - config.push_cert(other_cert.clone()).unwrap(), + config.push_cert(CertificatePem(other_cert.clone())).unwrap(), CertificateUploadResponse::WaitingOnKey, ); assert_eq!( - config.push_key(other_key.clone()).unwrap(), + config + .push_key(PrivateKeyPem(Zeroizing::new(other_key.clone()))) + .unwrap(), CertificateUploadResponse::CertKeyAccepted, ); assert_eq!(config.external_certificates.len(), 2); diff --git a/wicketd/tests/integration_tests/commission.rs b/wicketd/tests/integration_tests/commission.rs index 1201b3ae2e5..9439328a96c 100644 --- a/wicketd/tests/integration_tests/commission.rs +++ b/wicketd/tests/integration_tests/commission.rs @@ -33,6 +33,7 @@ use wicketd_commission_types_versions::latest::rack_setup::{ use wicketd_commission_types_versions::latest::update::{ StartUpdateOptions, StartUpdateParams, UpdateState, UpdateTargets, }; +use zeroize::Zeroizing; /// Wait for the SP inventory to become ready. async fn wait_for_sp_inventory( @@ -399,7 +400,9 @@ async fn test_commission_rss_config() { // 400. let err = ctx .commission_client - .post_rss_config_key(&PrivateKeyPem("a garbage key".to_string())) + .post_rss_config_key(&PrivateKeyPem(Zeroizing::new( + "a garbage key".to_string(), + ))) .await .expect_err("post_rss_config_key rejects an invalid pair"); assert_client_error(&err, StatusCode::BAD_REQUEST); diff --git a/workspace-hack/Cargo.toml b/workspace-hack/Cargo.toml index 8cfab998290..196e6c4aacd 100644 --- a/workspace-hack/Cargo.toml +++ b/workspace-hack/Cargo.toml @@ -164,7 +164,7 @@ usdt-impl-d8f496e17d97b5cb = { package = "usdt-impl", version = "0.5.0", default uuid = { version = "1.23.4", features = ["serde", "v4"] } x509-cert = { version = "0.2.5" } zerocopy = { version = "0.8.55", default-features = false, features = ["derive", "simd"] } -zeroize = { version = "1.9.0", features = ["aarch64", "std", "zeroize_derive"] } +zeroize = { version = "1.9.0", features = ["aarch64", "serde", "std", "zeroize_derive"] } zip-164d15cefe24d7eb = { package = "zip", version = "4.6.1", default-features = false, features = ["bzip2", "deflate", "jiff-02", "zstd"] } zip-3b31131e45eafb45 = { package = "zip", version = "0.6.6", default-features = false, features = ["bzip2", "deflate"] } @@ -322,7 +322,7 @@ vergen = { version = "9.1.0", features = ["cargo", "rustc"] } vergen-lib = { version = "9.1.0", features = ["cargo", "git", "rustc"] } x509-cert = { version = "0.2.5" } zerocopy = { version = "0.8.55", default-features = false, features = ["derive", "simd"] } -zeroize = { version = "1.9.0", features = ["aarch64", "std", "zeroize_derive"] } +zeroize = { version = "1.9.0", features = ["aarch64", "serde", "std", "zeroize_derive"] } zip-164d15cefe24d7eb = { package = "zip", version = "4.6.1", default-features = false, features = ["bzip2", "deflate", "jiff-02", "zstd"] } zip-3b31131e45eafb45 = { package = "zip", version = "0.6.6", default-features = false, features = ["bzip2", "deflate"] }