Skip to content

Commit a5e09f5

Browse files
committed
Improve security of endpoints
Skip deleting branch if main
1 parent 1b0f247 commit a5e09f5

File tree

10 files changed

+112
-116
lines changed

10 files changed

+112
-116
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use actix_web::{
2+
error::{ErrorInternalServerError, ErrorUnauthorized},
3+
Error,
4+
};
5+
use fplus_lib::{config::get_env_var_or_default, external_services::github::github_async_new};
6+
7+
pub async fn check_if_pull_request_opened_by_bot(
8+
owner: &str,
9+
repo: &str,
10+
pr_number: &u64,
11+
) -> Result<(), Error> {
12+
let gh_bot = get_env_var_or_default("BOT_USER");
13+
let gh = github_async_new(owner.to_string(), repo.to_string())
14+
.await
15+
.map_err(|e| ErrorInternalServerError(format!("Failed to get GitHub client: {e}")))?;
16+
let pr = gh
17+
.get_pull_request_by_number(*pr_number)
18+
.await
19+
.map_err(|e| ErrorInternalServerError(format!("Failed to get pull request: {e}")))?;
20+
21+
let login = pr
22+
.user
23+
.as_ref()
24+
.map(|user| user.login.as_str())
25+
.ok_or_else(|| {
26+
ErrorInternalServerError("User handle not found in pull request".to_string())
27+
})?;
28+
29+
if login.is_empty() {
30+
return Err(ErrorInternalServerError("User handle is empty".to_string()));
31+
}
32+
if login != gh_bot {
33+
return Err(ErrorUnauthorized(format!("Unauthorized user: {login}")));
34+
}
35+
Ok(())
36+
}

fplus-http-server/src/auth/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod gh_handle_auth;

fplus-http-server/src/main.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use fplus_lib::core::allocator::update_installation_ids_logic;
22
mod middleware;
33
use middleware::verifier_auth::VerifierAuth;
4+
mod auth;
45
pub(crate) mod router;
56

67
use actix_web::{
@@ -107,7 +108,6 @@ async fn main() -> std::io::Result<()> {
107108
.service(router::application::validate_application_proposal)
108109
.service(router::application::validate_application_approval)
109110
.service(router::application::validate_application_merge)
110-
.service(router::application::delete_branch)
111111
.service(router::application::cache_renewal)
112112
.service(router::application::update_from_issue)
113113
.service(router::application::submit_kyc)
@@ -116,7 +116,6 @@ async fn main() -> std::io::Result<()> {
116116
.service(router::verifier::verifiers)
117117
.service(router::allocator::allocators)
118118
.service(router::allocator::allocator)
119-
.service(router::allocator::delete)
120119
.service(router::allocator::create_allocator_from_json)
121120
.service(router::allocator::update_allocator_force)
122121
.service(router::allocator::check_if_repository_application_is_installed)

fplus-http-server/src/router/allocator.rs

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use actix_web::{
2-
delete,
32
error::{ErrorInternalServerError, ErrorNotFound},
43
get, post, web, HttpResponse, Responder,
54
};
@@ -70,24 +69,6 @@ pub async fn allocator(path: web::Path<(String, String)>) -> actix_web::Result<i
7069
}
7170
}
7271

73-
/**
74-
* Delete an allocator
75-
*
76-
* # Arguments
77-
* @param path: web::Path<(String, String)> - The owner and repo of the allocator
78-
*
79-
* # Returns
80-
* @return HttpResponse - The result of the operation
81-
*/
82-
#[delete("/allocator/{owner}/{repo}")]
83-
pub async fn delete(path: web::Path<(String, String)>) -> actix_web::Result<impl Responder> {
84-
let (owner, repo) = path.into_inner();
85-
allocators_db::delete_allocator(&owner, &repo)
86-
.await
87-
.map_err(ErrorInternalServerError)?;
88-
Ok(HttpResponse::Ok().finish())
89-
}
90-
9172
/**
9273
* Force updating allocator files from template.
9374
* It receives a list of changed files and allocators to update.

fplus-http-server/src/router/application.rs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,17 @@ use fplus_lib::core::{
77
application::file::{
88
DecreaseClientAllowanceVerifier, StorageProviderChangeVerifier, VerifierInput,
99
},
10-
ApplicationQueryParams, BranchDeleteInfo, CompleteGovernanceReviewInfo,
11-
CompleteNewApplicationApprovalInfo, CompleteNewApplicationProposalInfo, CreateApplicationInfo,
12-
DcReachedInfo, DecreaseAllowanceApprovalInfo, DecreaseAllowanceProposalInfo,
10+
ApplicationQueryParams, CompleteGovernanceReviewInfo, CompleteNewApplicationApprovalInfo,
11+
CompleteNewApplicationProposalInfo, CreateApplicationInfo, DcReachedInfo,
12+
DecreaseAllowanceApprovalInfo, DecreaseAllowanceProposalInfo,
1313
GetApplicationsByClientContractAddressQueryParams, GithubQueryParams, LDNApplication,
1414
MoreInfoNeeded, NotifyRefillInfo, StorageProvidersChangeApprovalInfo,
1515
StorageProvidersChangeProposalInfo, SubmitKYCInfo, TriggerSSAInfo, ValidationPullRequestData,
1616
VerifierActionsQueryParams,
1717
};
1818

19+
use crate::auth::gh_handle_auth::check_if_pull_request_opened_by_bot;
20+
1921
#[post("/application")]
2022
pub async fn create(info: web::Json<CreateApplicationInfo>) -> actix_web::Result<impl Responder> {
2123
let app = LDNApplication::new_from_issue(info.into_inner())
@@ -543,8 +545,8 @@ pub async fn validate_application_merge(
543545
owner,
544546
repo,
545547
} = info.into_inner();
546-
547548
if let Ok(pr_number) = pr_number.trim_matches('"').parse::<u64>() {
549+
check_if_pull_request_opened_by_bot(&owner, &repo, &pr_number).await?;
548550
let result = LDNApplication::validate_merge_application(pr_number, owner, repo)
549551
.await
550552
.map_err(ErrorInternalServerError)?;
@@ -554,15 +556,6 @@ pub async fn validate_application_merge(
554556
}
555557
}
556558

557-
#[post("/application/branch/delete")]
558-
pub async fn delete_branch(data: web::Json<BranchDeleteInfo>) -> actix_web::Result<impl Responder> {
559-
let info = data.into_inner();
560-
let result = LDNApplication::delete_branch(info.owner, info.repo, info.branch_name)
561-
.await
562-
.map_err(ErrorInternalServerError)?;
563-
Ok(HttpResponse::Ok().json(result))
564-
}
565-
566559
#[post("application/cache/renewal")]
567560
pub async fn cache_renewal(
568561
info: web::Json<GithubQueryParams>,
@@ -597,13 +590,14 @@ pub async fn check_for_changes(
597590
) -> actix_web::Result<impl Responder> {
598591
let ValidationPullRequestData {
599592
pr_number,
600-
user_handle,
593+
user_handle: _,
601594
owner,
602595
repo,
603596
} = info.into_inner();
604597

605598
if let Ok(pr_number) = pr_number.trim_matches('"').parse::<u64>() {
606-
let result = LDNApplication::check_for_changes(pr_number, &user_handle, owner, repo)
599+
check_if_pull_request_opened_by_bot(&owner, &repo, &pr_number).await?;
600+
let result = LDNApplication::check_for_changes(pr_number, owner, repo)
607601
.await
608602
.map_err(ErrorInternalServerError)?;
609603
Ok(HttpResponse::Ok().json(result))

fplus-lib/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ tfidf-summarizer = "2.0.0"
4242
ndarray = "0.16.1"
4343
strsim = "0.10"
4444
url = "2.5.4"
45+
snafu = "0.7.5"
4546

4647
[dev-dependencies]
4748
actix-rt = "2.9.0"

fplus-lib/src/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub fn default_env_vars() -> &'static HashMap<&'static str, &'static str> {
2020
m.insert("ALLOCATOR_GOVERNANCE_REPO", "Allocator-Governance-Staging");
2121
m.insert("ALLOCATOR_TEMPLATE_OWNER", "fidlabs");
2222
m.insert("ALLOCATOR_TEMPLATE_REPO", "allocator-template");
23-
m.insert("BOT_USER", "filplus-allocators-staging-bot[bot]");
23+
m.insert("BOT_USER", "filplus-dr-bot-ghapp[bot]");
2424
m.insert(
2525
"BACKEND_URL",
2626
"https://fp-core.dp04sa0tdc6pk.us-east-1.cs.amazonlightsail.com",

fplus-lib/src/core/mod.rs

Lines changed: 37 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,6 @@ pub struct TriggerSSAInfo {
8181
pub early_refill_comment: Option<String>,
8282
}
8383

84-
#[derive(Deserialize)]
85-
pub struct BranchDeleteInfo {
86-
pub owner: String,
87-
pub repo: String,
88-
pub branch_name: String,
89-
}
90-
9184
#[derive(Deserialize)]
9285
pub struct NewPrNumberAndFileSha {
9386
pub pr_number: u64,
@@ -1952,11 +1945,13 @@ impl LDNApplication {
19521945

19531946
let gh = github_async_new(self.github.owner.clone(), self.github.repo.clone()).await?;
19541947

1955-
gh.merge_pull_request(pr_number).await.map_err(|e| {
1956-
LDNError::Load(format!(
1957-
"Failed to merge pull request {pr_number}. Reason: {e}"
1958-
))
1959-
})?;
1948+
gh.merge_pull_request_and_delete_branch(&pr_number)
1949+
.await
1950+
.map_err(|e| {
1951+
LDNError::Load(format!(
1952+
"Failed to merge pull request {pr_number} or delete branch. Reason: {e}"
1953+
))
1954+
})?;
19601955

19611956
database::applications::merge_application_by_pr_number(
19621957
self.github.owner.clone(),
@@ -2249,29 +2244,31 @@ impl LDNApplication {
22492244
}
22502245
log::info!("- Application is in a valid state!");
22512246

2252-
Self::merge_application(pr_number, owner, repo).await?;
2247+
Self::merge_application_and_delete_branch(pr_number, owner, repo).await?;
22532248
return Ok(true);
22542249
} else if application.lifecycle.get_state() == AppState::Declined {
2255-
Self::merge_application(pr_number, owner, repo).await?;
2250+
Self::merge_application_and_delete_branch(pr_number, owner, repo).await?;
22562251
return Ok(true);
22572252
}
22582253

22592254
log::warn!("- Application is not in a valid state");
22602255
Ok(false)
22612256
}
22622257

2263-
pub async fn merge_application(
2258+
pub async fn merge_application_and_delete_branch(
22642259
pr_number: u64,
22652260
owner: String,
22662261
repo: String,
22672262
) -> Result<bool, LDNError> {
22682263
let gh = github_async_new(owner.to_string(), repo.to_string()).await?;
22692264

2270-
gh.merge_pull_request(pr_number).await.map_err(|e| {
2271-
LDNError::Load(format!(
2272-
"Failed to merge pull request {pr_number}. Reason: {e}"
2273-
))
2274-
})?;
2265+
gh.merge_pull_request_and_delete_branch(&pr_number)
2266+
.await
2267+
.map_err(|e| {
2268+
LDNError::Load(format!(
2269+
"Failed to merge pull request {pr_number} or delete branch. Reason: {e}"
2270+
))
2271+
})?;
22752272

22762273
database::applications::merge_application_by_pr_number(owner, repo, pr_number)
22772274
.await
@@ -2370,11 +2367,6 @@ impl LDNApplication {
23702367
log::info!("- Application is in a valid state!");
23712368
return Ok(true);
23722369
}
2373-
// let bot_user = get_env_var_or_default("BOT_USER");
2374-
// if author != bot_user {
2375-
// log::warn!("- Author is not the bot user");
2376-
// return Ok(false);
2377-
// }
23782370

23792371
log::info!("- Application is in a valid state");
23802372
Ok(true)
@@ -2745,18 +2737,11 @@ impl LDNApplication {
27452737

27462738
pub async fn check_for_changes(
27472739
pr_number: u64,
2748-
author: &str,
27492740
owner: String,
27502741
repo: String,
27512742
) -> Result<bool, LDNError> {
27522743
log::info!("Starting check_for_changes:");
27532744

2754-
let bot_user = get_env_var_or_default("BOT_USER");
2755-
if author != bot_user {
2756-
log::warn!("- Author is not the bot user");
2757-
return Err(LDNError::New("PR File edited by user".to_string()));
2758-
}
2759-
27602745
let gh: GithubWrapper = github_async_new(owner.clone(), repo.clone()).await?;
27612746
let result = Self::get_pr_files_and_app(owner.clone(), repo.clone(), pr_number).await;
27622747

@@ -3491,23 +3476,6 @@ impl LDNApplication {
34913476
Ok(())
34923477
}
34933478

3494-
pub async fn delete_branch(
3495-
owner: String,
3496-
repo: String,
3497-
branch_name: String,
3498-
) -> Result<bool, LDNError> {
3499-
let gh = github_async_new(owner, repo).await?;
3500-
let request = gh
3501-
.build_remove_ref_request(branch_name.clone())
3502-
.map_err(|e| LDNError::New(format!("build_remove_ref_request function failed: {e}")))?;
3503-
3504-
gh.remove_branch(request)
3505-
.await
3506-
.map_err(|e| LDNError::New(format!("Error deleting branch {branch_name} /// {e}")))?;
3507-
3508-
Ok(true)
3509-
}
3510-
35113479
async fn add_comment_to_issue(
35123480
issue_number: String,
35133481
owner: String,
@@ -4268,11 +4236,13 @@ _The initial issue can be edited in order to solve the request of the verifier.
42684236
if !application_file.allocation.0.is_empty() {
42694237
let gh = github_async_new(owner.to_string(), repo.to_string()).await?;
42704238

4271-
gh.merge_pull_request(pr_number).await.map_err(|e| {
4272-
LDNError::Load(format!(
4273-
"Failed to merge pull request {pr_number}. Reason: {e}"
4274-
))
4275-
})?;
4239+
gh.merge_pull_request_and_delete_branch(&pr_number)
4240+
.await
4241+
.map_err(|e| {
4242+
LDNError::Load(format!(
4243+
"Failed to merge pull request {pr_number} or delete branch. Reason: {e}"
4244+
))
4245+
})?;
42764246

42774247
database::applications::merge_application_by_pr_number(
42784248
owner.to_string(),
@@ -4712,7 +4682,8 @@ _The initial issue can be edited in order to solve the request of the verifier.
47124682
self.remove_first_pending_allocation(&application_file)
47134683
.await?;
47144684
} else {
4715-
self.remove_pending_refill(&app_model.pr_number).await?;
4685+
self.remove_pending_refill(&(app_model.pr_number as u64))
4686+
.await?;
47164687
}
47174688

47184689
let comment = format!(
@@ -4784,18 +4755,21 @@ _The initial issue can be edited in order to solve the request of the verifier.
47844755
Ok(())
47854756
}
47864757

4787-
async fn remove_pending_refill(&self, pr_number: &i64) -> Result<(), LDNError> {
4788-
Self::delete_branch(
4789-
self.github.owner.clone(),
4790-
self.github.repo.clone(),
4791-
self.branch_name.clone(),
4792-
)
4793-
.await?;
4758+
async fn remove_pending_refill(&self, pr_number: &u64) -> Result<(), LDNError> {
4759+
self.github
4760+
.delete_branch_safe(pr_number)
4761+
.await
4762+
.map_err(|e| {
4763+
LDNError::New(format!(
4764+
"Failed to delete branch for PR number: {pr_number} Reason: {e:?}"
4765+
))
4766+
})?;
4767+
47944768
database::applications::delete_application(
47954769
self.application_id.clone(),
47964770
self.github.owner.clone(),
47974771
self.github.repo.clone(),
4798-
*pr_number as u64,
4772+
*pr_number,
47994773
)
48004774
.await
48014775
.map_err(|e| {
@@ -5044,22 +5018,6 @@ impl LDNPullRequest {
50445018
Ok(())
50455019
}
50465020

5047-
pub async fn delete_branch(
5048-
application_id: String,
5049-
owner: String,
5050-
repo: String,
5051-
) -> Result<(), LDNError> {
5052-
let gh = github_async_new(owner.clone(), repo.clone()).await?;
5053-
let branch_name = LDNPullRequest::application_branch_name(&application_id);
5054-
let request = gh
5055-
.build_remove_ref_request(branch_name.clone())
5056-
.map_err(|e| LDNError::New(format!("build_remove_ref_request function failed: {e}")))?;
5057-
gh.remove_branch(request)
5058-
.await
5059-
.map_err(|e| LDNError::New(format!("Error deleting branch {branch_name} /// {e}")))?;
5060-
Ok(())
5061-
}
5062-
50635021
pub(super) fn application_branch_name(application_id: &str) -> String {
50645022
format!("Application/{application_id}")
50655023
}

0 commit comments

Comments
 (0)