From bd33253b240aaec84fc3e4b963c9bb92ba383c5d Mon Sep 17 00:00:00 2001 From: Ultradesu Date: Mon, 15 Sep 2025 14:14:54 +0300 Subject: [PATCH] Added query params to get values in plain text --- Cargo.lock | 2 ++ Cargo.toml | 2 +- src/main.rs | 45 ++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 79b574e..028ad5a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -112,6 +112,8 @@ dependencies = [ "humansize", "num-traits", "percent-encoding", + "serde", + "serde_json", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index c0e24e3..e302efc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "secret-reader" -version = "0.1.0" +version = "0.1.1" edition = "2021" [dependencies] diff --git a/src/main.rs b/src/main.rs index d7be2ec..ec20138 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,16 +1,16 @@ use anyhow::Result; use askama::Template; use axum::{ - extract::State, + extract::{Query, State}, http::StatusCode, - response::{Html, IntoResponse}, + response::{Html, IntoResponse, Response}, routing::get, Router, }; use clap::Parser; use k8s_openapi::api::core::v1::Secret; use kube::{Api, Client}; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::sync::Arc; use tracing::{error, info}; use tracing_subscriber; @@ -48,6 +48,12 @@ struct IndexTemplate { error: Option, } +#[derive(Debug, Deserialize)] +struct SecretQuery { + name: String, + field: String, +} + async fn read_secrets(state: &AppState) -> Result> { let secrets_api: Api = Api::namespaced(state.client.clone(), &state.namespace); let mut result = Vec::new(); @@ -125,6 +131,38 @@ async fn health_handler() -> impl IntoResponse { "OK" } +async fn secret_handler( + Query(params): Query, + State(state): State>, +) -> Response { + info!("Fetching secret: {} field: {}", params.name, params.field); + + let secrets_api: Api = Api::namespaced(state.client.clone(), &state.namespace); + + match secrets_api.get(¶ms.name).await { + Ok(secret) => { + if let Some(data) = secret.data { + if let Some(value) = data.get(¶ms.field) { + let decoded = String::from_utf8_lossy(&value.0).to_string(); + return decoded.into_response(); + } + } + + if let Some(string_data) = secret.string_data { + if let Some(value) = string_data.get(¶ms.field) { + return value.clone().into_response(); + } + } + + (StatusCode::NOT_FOUND, format!("Field '{}' not found in secret '{}'", params.field, params.name)).into_response() + } + Err(e) => { + error!("Failed to read secret {}: {}", params.name, e); + (StatusCode::NOT_FOUND, format!("Secret '{}' not found: {}", params.name, e)).into_response() + } + } +} + #[tokio::main] async fn main() -> Result<()> { tracing_subscriber::fmt::init(); @@ -151,6 +189,7 @@ async fn main() -> Result<()> { let app = Router::new() .route("/", get(index_handler)) .route("/health", get(health_handler)) + .route("/secret", get(secret_handler)) .with_state(state); let addr = format!("0.0.0.0:{}", args.port);