From 61c47d735abef8d7f1ead48b5f0a3437186d1105 Mon Sep 17 00:00:00 2001 From: snow flurry Date: Thu, 15 Aug 2024 21:19:59 -0700 Subject: [PATCH] omyacid: default username in /vendor-data --- omyacid/src/main.rs | 38 +++++++++++++++++++++++++++++-- omyacid/src/model.rs | 5 ++++ omyacid/templates/meta-data.yml | 7 +----- omyacid/templates/vendor-data.yml | 6 +++++ 4 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 omyacid/templates/vendor-data.yml diff --git a/omyacid/src/main.rs b/omyacid/src/main.rs index 971df4b..02355b6 100644 --- a/omyacid/src/main.rs +++ b/omyacid/src/main.rs @@ -43,7 +43,6 @@ async fn get_meta_data( inst_name: &inst.name, // XXX: this is very silly imo ssh_pubkeys: ssh_pubkeys.iter().collect(), - username: Some(ctx.cfg().cloud.admin_user.as_ref()), }; meta.render().map_err(|e| { @@ -88,6 +87,41 @@ async fn get_user_data( } } +#[instrument(skip(ctx))] +async fn get_vendor_data( + State(ctx): State, + ConnectInfo(addr): ConnectInfo, +) -> Result { + tracing::info!("Handling /vendor-data"); + + // All of the vendor data so far is handled globally, so this isn't really + // necessary. But it might help avoid an attacker trying to sniff for the + // admin username from an unknown instance. + if let IpAddr::V4(ip) = addr.ip() { + match ctx.get_instance(ip).await { + Ok(_) => { + let data = model::VendorData { + username: Some(&ctx.cfg().cloud.admin_user), + }; + data.render().map_err(|e| { + tracing::error!("Renderer error: {e}"); + StatusCode::INTERNAL_SERVER_ERROR + }) + } + Err(err) => { + tracing::error!("{err}"); + Err(StatusCode::INTERNAL_SERVER_ERROR) + } + _ => { + tracing::warn!("Request from unregistered server {ip}"); + Err(StatusCode::FORBIDDEN) + } + } + } else { + Err(StatusCode::BAD_REQUEST) + } +} + async fn ignored() -> &'static str { "" } @@ -131,7 +165,7 @@ async fn main() -> ExitCode { let app = Router::new() .route("/meta-data", get(get_meta_data)) .route("/user-data", get(get_user_data)) - .route("/vendor-data", get(ignored)) + .route("/vendor-data", get(get_vendor_data)) .route("/network-config", get(ignored)) .with_state(ctx); if let Err(err) = axum::serve( diff --git a/omyacid/src/model.rs b/omyacid/src/model.rs index b2d0e25..3e4867c 100644 --- a/omyacid/src/model.rs +++ b/omyacid/src/model.rs @@ -4,5 +4,10 @@ use askama::Template; pub struct Metadata<'a> { pub inst_name: &'a str, pub ssh_pubkeys: Vec<&'a String>, +} + +#[derive(Template)] +#[template(path = "vendor-data.yml")] +pub struct VendorData<'a> { pub username: Option<&'a str>, } diff --git a/omyacid/templates/meta-data.yml b/omyacid/templates/meta-data.yml index 0809914..0868c3c 100644 --- a/omyacid/templates/meta-data.yml +++ b/omyacid/templates/meta-data.yml @@ -5,9 +5,4 @@ public-keys: {% for key in ssh_pubkeys -%} - "{{ key }}" {% endfor %} -{%- endif -%} -{% if let Some(user) = username -%} -system_info: - default_user: - name: "{{ user }}" -{%- endif %} \ No newline at end of file +{%- endif -%} \ No newline at end of file diff --git a/omyacid/templates/vendor-data.yml b/omyacid/templates/vendor-data.yml new file mode 100644 index 0000000..2336020 --- /dev/null +++ b/omyacid/templates/vendor-data.yml @@ -0,0 +1,6 @@ +#cloud-config +{% if let Some(user) = username -%} +system_info: + default_user: + name: "{{ user }}" +{%- endif %} \ No newline at end of file