Skip to content

Commit

Permalink
fix: provide a way to retrieve public vs non-public frontend config
Browse files Browse the repository at this point in the history
Some part of the configuration might be considered confidential. So
we do remove most of the configuration information and create a
dedicated, public endpoint.
  • Loading branch information
ctron committed Apr 15, 2024
1 parent 2a2c3fa commit 15b99c1
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 18 deletions.
44 changes: 37 additions & 7 deletions spog/api/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ use anyhow::bail;
use spog_model::config::Configuration;
use std::borrow::Cow;
use std::path::PathBuf;
use std::sync::Arc;
use tracing::instrument;
use trustification_auth::authenticator::Authenticator;
use trustification_infrastructure::new_auth;

pub struct Config {
content: Configuration,
Expand All @@ -15,27 +18,49 @@ pub struct Config {

impl Config {
#[instrument(skip(self), err)]
async fn retrieve(&self) -> anyhow::Result<Cow<'_, Configuration>> {
async fn retrieve(&self, public: bool) -> anyhow::Result<Cow<'_, Configuration>> {
Ok(match &self.source {
Some(config) => {
// FIXME: need to cache instead re-parsing every time
// TODO: when we cache the result, attach a probe to it which fails if loading fails
let content = tokio::fs::read(config).await?;
Cow::Owned(serde_yaml::from_slice(&content)?)
let mut result = serde_yaml::from_slice(&content)?;
if public {
result = Self::make_public(result);
}
Cow::Owned(result)
}
None => Cow::Borrowed(&self.content),
})
}

fn make_public(config: Configuration) -> Configuration {
Configuration {
global: config.global,
..Default::default()
}
}
}

pub async fn get_config(config: web::Data<Config>) -> HttpResponse {
match config.retrieve().await {
pub async fn get_config(config: &Config, public: bool) -> HttpResponse {
match config.retrieve(public).await {
Ok(config) => HttpResponse::Ok().json(&config),
Err(err) => HttpResponse::InternalServerError().body(err.to_string()),
}
}

pub(crate) async fn configurator(source: Option<PathBuf>) -> anyhow::Result<impl Fn(&mut ServiceConfig) + Clone> {
pub async fn get_private_config(config: web::Data<Config>) -> HttpResponse {
get_config(&config, false).await
}

pub async fn get_public_config(config: web::Data<Config>) -> HttpResponse {
get_config(&config, true).await
}

pub(crate) async fn configurator(
source: Option<PathBuf>,
auth: Option<Arc<Authenticator>>,
) -> anyhow::Result<impl Fn(&mut ServiceConfig) + Clone> {
let content = serde_yaml::from_slice(include_bytes!("default.yaml"))?;

// do an initial check
Expand All @@ -53,7 +78,7 @@ pub(crate) async fn configurator(source: Option<PathBuf>) -> anyhow::Result<impl
source: Some(source),
};

let _ = config.retrieve().await?;
let _ = config.retrieve(false).await?;

config
}
Expand All @@ -69,7 +94,12 @@ pub(crate) async fn configurator(source: Option<PathBuf>) -> anyhow::Result<impl
Ok(move |service_config: &mut ServiceConfig| {
service_config
.app_data(config.clone())
.service(web::resource("/api/v1/config").to(get_config));
.service(
web::resource("/api/v1/config")
.wrap(new_auth!(auth.clone()))
.to(get_private_config),
)
.service(web::resource("/api/v1/config/public").to(get_public_config));
})
}

Expand Down
4 changes: 2 additions & 2 deletions spog/api/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ impl Server {
provider: provider.clone(),
});

let config_configurator = config::configurator(self.run.config).await?;

let (authn, authz) = self.run.auth.split(self.run.devmode)?.unzip();
let authenticator: Option<Arc<Authenticator>> = Authenticator::from_config(authn)
.await
Expand All @@ -63,6 +61,8 @@ impl Server {
log::info!("Snyk token is present");
}

let config_configurator = config::configurator(self.run.config, authenticator.clone()).await?;

let crda = self
.run
.crda_url
Expand Down
11 changes: 9 additions & 2 deletions spog/ui/crates/backend/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,15 @@ impl ConfigService {
Self { backend, access_token }
}

pub async fn get_config(&self) -> Result<Configuration, ApiError> {
let url = self.backend.join(Endpoint::Api, "/api/v1/config")?;
pub async fn get_config(&self, public: bool) -> Result<Configuration, ApiError> {
let url = self.backend.join(
Endpoint::Api,
if public {
"/api/v1/config/public"
} else {
"/api/v1/config"
},
)?;

let response = gloo_net::http::Request::get(url.as_str())
.latest_access_token(&self.access_token)
Expand Down
8 changes: 5 additions & 3 deletions spog/ui/crates/utils/src/config/components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use yew_oauth2::hook::use_latest_access_token;
pub struct ConfigurationProperties {
#[prop_or_default]
pub children: Children,
#[prop_or_default]
pub public: bool,
}

#[function_component(Configuration)]
Expand All @@ -17,13 +19,13 @@ pub fn configuration(props: &ConfigurationProperties) -> Html {
let access_token = use_latest_access_token();

let config = use_async_with_cloned_deps(
|backend| async {
|(backend, public)| async move {
ConfigService::new(backend, access_token)
.get_config()
.get_config(public)
.await
.map(Rc::new)
},
backend,
(backend, props.public),
);

match &*config {
Expand Down
2 changes: 1 addition & 1 deletion spog/ui/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ fn application_with_backend() -> Html {
scopes={backend.endpoints.oidc.scopes()}
{login_options}
>
<Configuration>
<Configuration public=true>
{ consent(html!(
<BackdropViewer>
<ToastViewer>
Expand Down
9 changes: 6 additions & 3 deletions spog/ui/src/console/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use spog_ui_components::{
theme::DarkModeEntry,
};
use spog_ui_navigation::{AppRoute, View};
use spog_ui_utils::config::components::Configuration;
use spog_ui_utils::{analytics::*, config::*, hints::*};
use yew::prelude::*;
use yew_consent::hook::use_consent_context;
Expand Down Expand Up @@ -203,9 +204,11 @@ fn authenticated_page(props: &ChildrenProperties) -> Html {
);

html!(
<Page {brand} {sidebar} {tools}>
{ props.children.clone() }
</Page>
<Configuration>
<Page {brand} {sidebar} {tools}>
{ props.children.clone() }
</Page>
</Configuration>
)
}

Expand Down

0 comments on commit 15b99c1

Please sign in to comment.