Skip to content

Commit

Permalink
Refuse GitHub auth on non-https schemes.
Browse files Browse the repository at this point in the history
This is mostly to generate better error messages on misconfiguration.
  • Loading branch information
bittrance committed Dec 27, 2023
1 parent 232fbee commit 58741ae
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 14 deletions.
2 changes: 2 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ pub enum GitOpsError {
NotifyError(String),
#[error("Failed to launch action: {0}")]
ActionError(std::io::Error),
#[error("Auth only on HTTPS URLs: {0}")]
GitHubAuthNonHttpsUrl(String),
#[error("Missing private key file: {0}")]
GitHubMissingPrivateKeyFile(std::io::Error),
#[error("Malformed private RS256 key: {0}")]
Expand Down
59 changes: 45 additions & 14 deletions src/github.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{
time::Duration,
};

use gix::{ObjectId, Url};
use gix::{url::Scheme, ObjectId, Url};
use jwt_simple::prelude::{Claims, RS256KeyPair, RSAKeyPairLike};
use reqwest::{
blocking::ClientBuilder,
Expand Down Expand Up @@ -43,21 +43,20 @@ impl UrlProvider for GithubUrlProvider {
}

fn auth_url(&self) -> Result<Url, GitOpsError> {
if self.url.scheme != Scheme::Https {
let mut buf = Vec::new();
self.url.write_to(&mut buf).unwrap();
let url_str = String::from_utf8(buf).unwrap_or_else(|_| "<unparseable>".to_owned());
return Err(GitOpsError::GitHubAuthNonHttpsUrl(url_str));
}
let client = http_client();
let jwt_token = generate_jwt(&self.app_id, &self.private_key_file)?;
let installation_id = get_installation_id(&self.repo_slug(), &client, &jwt_token)?;
let access_token = get_access_token(installation_id, &client, &jwt_token)?;
// TODO Newer version of gix-url has set_username/set_password
Ok(Url::from_parts(
self.url.scheme.clone(),
Some("x-access-token".to_owned()),
Some(access_token),
self.url.host().map(str::to_owned),
self.url.port,
self.url.path.clone(),
false,
)
.unwrap())
let mut auth_url = self.url.clone();
auth_url.set_user(Some("x-access-token".to_owned()));
auth_url.set_password(Some(access_token));
Ok(auth_url)
}
}

Expand Down Expand Up @@ -160,7 +159,6 @@ pub fn update_commit_status(
status: GitHubStatus,
message: &str,
) -> Result<(), GitOpsError> {
let config = config.clone();
let client = http_client();
let jwt_token = generate_jwt(&config.app_id, &config.private_key_file)?;
let installation_id = get_installation_id(repo_slug, &client, &jwt_token)?;
Expand All @@ -172,7 +170,7 @@ pub fn update_commit_status(
);
let body = serde_json::json!({
"state": status,
"context": config.status_context.unwrap(),
"context": config.status_context,
"description": message,
});
let res = client
Expand Down Expand Up @@ -241,3 +239,36 @@ pub fn github_watcher(
Ok(())
}
}

#[cfg(test)]
mod tests {
use super::*;
use std::path::PathBuf;

#[test]
fn github_url_provider_slug() {
let url = Url::try_from("https://github.com/bittrance/kitops.git".to_owned()).unwrap();
let config = GithubConfig {
app_id: "1234".to_owned(),
private_key_file: PathBuf::from("ze-key"),
status_context: Some("ze-context".to_owned()),
};
let provider = GithubUrlProvider::new(url, &config);
assert_eq!(provider.repo_slug(), "bittrance/kitops");
}

#[test]
fn github_url_provider_refuses_http_on_auth() {
let url = Url::try_from("http://some.site/bittrance/kitops".to_owned()).unwrap();
let config = GithubConfig {
app_id: "1234".to_owned(),
private_key_file: PathBuf::from("ze-key"),
status_context: Some("ze-context".to_owned()),
};
let provider = GithubUrlProvider::new(url, &config);
assert!(matches!(
provider.auth_url(),
Err(GitOpsError::GitHubAuthNonHttpsUrl(_))
));
}
}

0 comments on commit 58741ae

Please sign in to comment.