mirror of
https://github.com/getnora-io/nora.git
synced 2026-04-12 12:40:31 +00:00
feat: upstream auth for all protocols (Docker, Maven, npm, PyPI)
Wire up basic auth credentials for upstream registry proxying: - Docker: pass configured auth to Bearer token requests - Maven: support url|auth format in NORA_MAVEN_PROXIES env var - npm: add NORA_NPM_PROXY_AUTH env var - PyPI: add NORA_PYPI_PROXY_AUTH env var - Mask credentials in logs (never log plaintext passwords) Config examples: NORA_DOCKER_UPSTREAMS="https://registry.corp.com|user:pass" NORA_MAVEN_PROXIES="https://nexus.corp.com/maven2|user:pass" NORA_NPM_PROXY_AUTH="user:pass" NORA_PYPI_PROXY_AUTH="user:pass"
This commit is contained in:
@@ -12,6 +12,7 @@ use axum::{
|
||||
routing::{get, put},
|
||||
Router,
|
||||
};
|
||||
use base64::{engine::general_purpose::STANDARD, Engine};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -49,10 +50,17 @@ async fn download(State(state): State<Arc<AppState>>, Path(path): Path<String>)
|
||||
return with_content_type(&path, data).into_response();
|
||||
}
|
||||
|
||||
for proxy_url in &state.config.maven.proxies {
|
||||
let url = format!("{}/{}", proxy_url.trim_end_matches('/'), path);
|
||||
for proxy in &state.config.maven.proxies {
|
||||
let url = format!("{}/{}", proxy.url().trim_end_matches('/'), path);
|
||||
|
||||
match fetch_from_proxy(&state.http_client, &url, state.config.maven.proxy_timeout).await {
|
||||
match fetch_from_proxy(
|
||||
&state.http_client,
|
||||
&url,
|
||||
state.config.maven.proxy_timeout,
|
||||
proxy.auth(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(data) => {
|
||||
state.metrics.record_download("maven");
|
||||
state.metrics.record_cache_miss();
|
||||
@@ -124,13 +132,14 @@ async fn fetch_from_proxy(
|
||||
client: &reqwest::Client,
|
||||
url: &str,
|
||||
timeout_secs: u64,
|
||||
auth: Option<&str>,
|
||||
) -> Result<Vec<u8>, ()> {
|
||||
let response = client
|
||||
.get(url)
|
||||
.timeout(Duration::from_secs(timeout_secs))
|
||||
.send()
|
||||
.await
|
||||
.map_err(|_| ())?;
|
||||
let mut request = client.get(url).timeout(Duration::from_secs(timeout_secs));
|
||||
if let Some(credentials) = auth {
|
||||
let encoded = STANDARD.encode(credentials);
|
||||
request = request.header("Authorization", format!("Basic {}", encoded));
|
||||
}
|
||||
let response = request.send().await.map_err(|_| ())?;
|
||||
|
||||
if !response.status().is_success() {
|
||||
return Err(());
|
||||
|
||||
Reference in New Issue
Block a user