1 Commits

Author SHA1 Message Date
Tom Alexander
613026b326 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
2024-09-29 16:54:58 -04:00
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(