Adding repo whitelist.
Some checks failed
semver Build semver has succeeded
format Build format has succeeded
clippy Build clippy has failed
build Build build has succeeded
rust-test Build rust-test has succeeded

This commit is contained in:
Tom Alexander 2024-09-29 16:27:04 -04:00
parent cd56bb2fe1
commit 613026b326
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
5 changed files with 50 additions and 7 deletions

View File

@ -33,3 +33,4 @@ format: ## Auto-format source files.
.PHONY: clean
clean:
> $(MAKE) -C docker/webhook_bridge_development clean
> rm -rf target

View File

@ -1,3 +1,6 @@
use std::collections::HashSet;
use std::sync::Arc;
use kube::Client;
use crate::gitea_client::GiteaClient;
@ -6,4 +9,5 @@ use crate::gitea_client::GiteaClient;
pub(crate) struct AppState {
pub(crate) kubernetes_client: Client,
pub(crate) gitea: GiteaClient,
pub(crate) allowed_repos: Arc<HashSet<String>>,
}

View File

@ -16,7 +16,7 @@ pub(crate) struct HookPush {
commits: Vec<HookCommit>,
total_commits: u64,
head_commit: HookCommit,
repository: HookRepository,
pub(crate) repository: HookRepository,
pusher: HookUser,
sender: HookUser,
}
@ -55,7 +55,7 @@ pub(crate) struct HookRepository {
id: u64,
owner: HookUser,
name: String,
full_name: String,
pub(crate) full_name: String,
description: String,
empty: bool,
private: bool,

View File

@ -1,4 +1,6 @@
#![forbid(unsafe_code)]
use std::collections::HashSet;
use std::sync::Arc;
use std::time::Duration;
use axum::http::StatusCode;
@ -35,7 +37,8 @@ pub async fn init_tracing() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::registry()
.with(
tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| {
"webhook_bridge=info,tower_http=debug,axum::rejection=trace".into()
"webhookbridge=info,webhook_bridge=info,local_trigger=info,tower_http=debug,axum::rejection=trace"
.into()
}),
)
.with(tracing_subscriber::fmt::layer())
@ -52,6 +55,15 @@ pub async fn launch_server() -> Result<(), Box<dyn std::error::Error>> {
let gitea_api_token = std::env::var("WEBHOOK_BRIDGE_OAUTH_TOKEN")?;
let gitea = GiteaClient::new(gitea_api_root, gitea_api_token);
let allowed_repos = std::env::var("WEBHOOK_BRIDGE_REPO_WHITELIST")?;
let allowed_repos: HashSet<_> = allowed_repos
.split(",")
.filter(|s| !s.is_empty())
.map(str::to_owned)
.collect();
tracing::debug!("Using repo whitelist: {:?}", allowed_repos);
let allowed_repos = HashSet::new();
let app = Router::new()
.route("/hook", post(hook))
.layer(middleware::from_fn(verify_signature))
@ -64,6 +76,7 @@ pub async fn launch_server() -> Result<(), Box<dyn std::error::Error>> {
.with_state(AppState {
kubernetes_client,
gitea,
allowed_repos: Arc::new(allowed_repos),
});
let listener = tokio::net::TcpListener::bind("0.0.0.0:9988").await?;
@ -83,9 +96,19 @@ pub async fn local_trigger(payload: &str) -> Result<(), Box<dyn std::error::Erro
let gitea_api_token = std::env::var("WEBHOOK_BRIDGE_OAUTH_TOKEN")?;
let gitea = GiteaClient::new(gitea_api_root, gitea_api_token);
let allowed_repos = std::env::var("WEBHOOK_BRIDGE_REPO_WHITELIST")
.ok()
.unwrap_or_else(String::new);
let allowed_repos: HashSet<_> = allowed_repos
.split(",")
.filter(|s| !s.is_empty())
.map(str::to_owned)
.collect();
tracing::debug!("Using repo whitelist: {:?}", allowed_repos);
let webhook_payload: HookPush = serde_json::from_str(payload)?;
handle_push(gitea, kubernetes_client, webhook_payload).await?;
handle_push(gitea, kubernetes_client, &allowed_repos, webhook_payload).await?;
Ok(())
}

View File

@ -1,3 +1,5 @@
use std::borrow::Borrow;
use std::collections::HashSet;
use std::future::Future;
use axum::async_trait;
@ -40,9 +42,14 @@ pub(crate) async fn hook(
debug!("REQ: {:?}", payload);
match payload {
HookRequest::Push(webhook_payload) => {
handle_push(state.gitea, state.kubernetes_client, webhook_payload)
.await
.expect("Failed to handle push event.");
handle_push(
state.gitea,
state.kubernetes_client,
state.allowed_repos.borrow(),
webhook_payload,
)
.await
.expect("Failed to handle push event.");
(
StatusCode::OK,
Json(HookResponse {
@ -167,11 +174,19 @@ fn hex_to_bytes(s: &str) -> Option<Vec<u8>> {
pub(crate) async fn handle_push(
gitea: GiteaClient,
kubernetes_client: kube::Client,
allowed_repos: &HashSet<String>,
webhook_payload: HookPush,
) -> Result<(), Box<dyn std::error::Error>> {
let repo_owner = webhook_payload.get_repo_owner()?;
let repo_name = webhook_payload.get_repo_name()?;
let pull_base_sha = webhook_payload.get_pull_base_sha()?;
if !allowed_repos.contains(&webhook_payload.repository.full_name) {
tracing::info!(
"{} is not an allowed repository.",
webhook_payload.repository.full_name
);
return Ok(());
}
let repo_tree = gitea.get_tree(repo_owner, repo_name, pull_base_sha).await?;
let remote_config = discover_webhook_bridge_config(&gitea, &repo_tree).await?;
let pipelines = discover_matching_push_triggers(