From 5bc083b5d5bc3a746872bcbed8e28cb7d3c98927 Mon Sep 17 00:00:00 2001 From: Ian Stanton Date: Mon, 17 Apr 2023 20:52:17 -0400 Subject: [PATCH 1/3] Add simple auth check --- trunk/cli/src/commands/publish.rs | 10 ++++++---- trunk/trunk-registry/src/errors.rs | 6 +++++- trunk/trunk-registry/src/publish.rs | 7 +++++++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/trunk/cli/src/commands/publish.rs b/trunk/cli/src/commands/publish.rs index 212459032..f94a744a4 100644 --- a/trunk/cli/src/commands/publish.rs +++ b/trunk/cli/src/commands/publish.rs @@ -2,8 +2,8 @@ use super::SubCommand; use crate::commands::publish::PublishError::InvalidExtensionName; use async_trait::async_trait; use clap::Args; -use hyper::header::CONTENT_TYPE; -use reqwest::header::HeaderMap; +use reqwest::header::CONTENT_TYPE; +use reqwest::header::{AUTHORIZATION, HeaderMap}; use serde_json::json; use std::fs; use std::path::PathBuf; @@ -66,9 +66,11 @@ impl SubCommand for PublishCommand { }; let mut headers = HeaderMap::new(); headers.insert(CONTENT_TYPE, "application/octet-stream".parse().unwrap()); + // Add token header from env var + headers.insert(AUTHORIZATION, "".parse().unwrap()); let file_part = reqwest::multipart::Part::bytes(file) .file_name(name) - .headers(headers); + .headers(headers.clone()); let m = json!({ "name": self.name, "vers": self.version, @@ -78,7 +80,7 @@ impl SubCommand for PublishCommand { "license": self.license, "repository": self.repository }); - let metadata = reqwest::multipart::Part::text(m.to_string()); + let metadata = reqwest::multipart::Part::text(m.to_string()).headers(headers); let form = reqwest::multipart::Form::new() .part("metadata", metadata) .part("file", file_part); diff --git a/trunk/trunk-registry/src/errors.rs b/trunk/trunk-registry/src/errors.rs index 2af82187a..79a7e9b48 100644 --- a/trunk/trunk-registry/src/errors.rs +++ b/trunk/trunk-registry/src/errors.rs @@ -1,6 +1,6 @@ //! Custom errors types for extension registry use actix_multipart::MultipartError; -use actix_web::error; +use actix_web::{error}; use aws_sdk_s3::error::SdkError; use aws_sdk_s3::operation::put_object::PutObjectError; use thiserror::Error; @@ -23,6 +23,10 @@ pub enum ExtensionRegistryError { #[error("response error")] ResponseError(), + /// an authorization error + #[error("authorization error")] + AuthorizationError(), + /// a payload error #[error("payload error")] PayloadError(#[from] error::PayloadError), diff --git a/trunk/trunk-registry/src/publish.rs b/trunk/trunk-registry/src/publish.rs index 176878a26..8f495915e 100644 --- a/trunk/trunk-registry/src/publish.rs +++ b/trunk/trunk-registry/src/publish.rs @@ -6,11 +6,13 @@ use crate::uploader::upload_extension; use crate::views::extension_publish::ExtensionUpload; use actix_multipart::Multipart; use actix_web::{error, post, web, HttpResponse}; +use actix_web::http::header::{AUTHORIZATION}; use aws_config::SdkConfig; use aws_sdk_s3; use aws_sdk_s3::primitives::ByteStream; use futures::TryStreamExt; use sqlx::{Pool, Postgres}; +use crate::errors::ExtensionRegistryError::{AuthorizationError}; const MAX_SIZE: usize = 262_144; // max payload size is 256k @@ -29,6 +31,11 @@ pub async fn publish( let mut metadata = web::BytesMut::new(); let mut file = web::BytesMut::new(); while let Some(mut field) = payload.try_next().await? { + let headers = field.headers(); + let auth = headers.get(AUTHORIZATION).unwrap(); + if auth != "" { + return Err(AuthorizationError()); + } // Field is stream of Bytes while let Some(chunk) = field.try_next().await? { // limit max size of in-memory payload From 1a167a1e5da6728ad5958f12f87c6b0d41fd7868 Mon Sep 17 00:00:00 2001 From: Ian Stanton Date: Mon, 17 Apr 2023 20:54:16 -0400 Subject: [PATCH 2/3] fmt --- trunk/cli/src/commands/publish.rs | 2 +- trunk/trunk-registry/src/errors.rs | 2 +- trunk/trunk-registry/src/publish.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/trunk/cli/src/commands/publish.rs b/trunk/cli/src/commands/publish.rs index f94a744a4..856cc8d2d 100644 --- a/trunk/cli/src/commands/publish.rs +++ b/trunk/cli/src/commands/publish.rs @@ -3,7 +3,7 @@ use crate::commands::publish::PublishError::InvalidExtensionName; use async_trait::async_trait; use clap::Args; use reqwest::header::CONTENT_TYPE; -use reqwest::header::{AUTHORIZATION, HeaderMap}; +use reqwest::header::{HeaderMap, AUTHORIZATION}; use serde_json::json; use std::fs; use std::path::PathBuf; diff --git a/trunk/trunk-registry/src/errors.rs b/trunk/trunk-registry/src/errors.rs index 79a7e9b48..12f1c788a 100644 --- a/trunk/trunk-registry/src/errors.rs +++ b/trunk/trunk-registry/src/errors.rs @@ -1,6 +1,6 @@ //! Custom errors types for extension registry use actix_multipart::MultipartError; -use actix_web::{error}; +use actix_web::error; use aws_sdk_s3::error::SdkError; use aws_sdk_s3::operation::put_object::PutObjectError; use thiserror::Error; diff --git a/trunk/trunk-registry/src/publish.rs b/trunk/trunk-registry/src/publish.rs index 8f495915e..bae91364f 100644 --- a/trunk/trunk-registry/src/publish.rs +++ b/trunk/trunk-registry/src/publish.rs @@ -2,17 +2,17 @@ use crate::config::Config; use crate::errors::ExtensionRegistryError; +use crate::errors::ExtensionRegistryError::AuthorizationError; use crate::uploader::upload_extension; use crate::views::extension_publish::ExtensionUpload; use actix_multipart::Multipart; +use actix_web::http::header::AUTHORIZATION; use actix_web::{error, post, web, HttpResponse}; -use actix_web::http::header::{AUTHORIZATION}; use aws_config::SdkConfig; use aws_sdk_s3; use aws_sdk_s3::primitives::ByteStream; use futures::TryStreamExt; use sqlx::{Pool, Postgres}; -use crate::errors::ExtensionRegistryError::{AuthorizationError}; const MAX_SIZE: usize = 262_144; // max payload size is 256k From 88c87d7f1b84cfccd3de6219cc6dfa22b4b8864b Mon Sep 17 00:00:00 2001 From: Ian Stanton Date: Mon, 17 Apr 2023 21:22:45 -0400 Subject: [PATCH 3/3] Read AUTH_TOKEN from env var in CLI and registry --- trunk/cli/Cargo.toml | 2 +- trunk/cli/src/commands/publish.rs | 5 +++-- trunk/trunk-registry/src/config.rs | 3 +++ trunk/trunk-registry/src/publish.rs | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/trunk/cli/Cargo.toml b/trunk/cli/Cargo.toml index 7fbf31cc7..13f92b930 100644 --- a/trunk/cli/Cargo.toml +++ b/trunk/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pg-trunk" -version = "0.2.2" +version = "0.3.0" edition = "2021" authors = ["Steven Miller", "Ian Stanton"] description = "A package manager for PostgreSQL extensions" diff --git a/trunk/cli/src/commands/publish.rs b/trunk/cli/src/commands/publish.rs index 856cc8d2d..d4b854fee 100644 --- a/trunk/cli/src/commands/publish.rs +++ b/trunk/cli/src/commands/publish.rs @@ -5,8 +5,8 @@ use clap::Args; use reqwest::header::CONTENT_TYPE; use reqwest::header::{HeaderMap, AUTHORIZATION}; use serde_json::json; -use std::fs; use std::path::PathBuf; +use std::{env, fs}; use tokio_task_manager::Task; #[derive(Args)] @@ -67,7 +67,8 @@ impl SubCommand for PublishCommand { let mut headers = HeaderMap::new(); headers.insert(CONTENT_TYPE, "application/octet-stream".parse().unwrap()); // Add token header from env var - headers.insert(AUTHORIZATION, "".parse().unwrap()); + let auth = env::var("AUTH_TOKEN").unwrap_or_else(|_| "".to_owned()); + headers.insert(AUTHORIZATION, auth.parse()?); let file_part = reqwest::multipart::Part::bytes(file) .file_name(name) .headers(headers.clone()); diff --git a/trunk/trunk-registry/src/config.rs b/trunk/trunk-registry/src/config.rs index eb6a31722..32b14b8e8 100644 --- a/trunk/trunk-registry/src/config.rs +++ b/trunk/trunk-registry/src/config.rs @@ -1,3 +1,4 @@ +use actix_web::http::header::HeaderValue; use std::env; #[derive(Debug, Clone)] @@ -7,6 +8,7 @@ pub struct Config { pub region: Option, pub aws_access_key: String, pub aws_secret_key: String, + pub auth_token: HeaderValue, } // TODO(ianstanton) Fix load from .env @@ -21,6 +23,7 @@ impl Default for Config { region: Some(from_env_default("S3_REGION", "")), aws_access_key: from_env_default("AWS_ACCESS_KEY", ""), aws_secret_key: from_env_default("AWS_SECRET_KEY", ""), + auth_token: from_env_default("AUTH_TOKEN", "").parse().unwrap(), } } } diff --git a/trunk/trunk-registry/src/publish.rs b/trunk/trunk-registry/src/publish.rs index bae91364f..865850197 100644 --- a/trunk/trunk-registry/src/publish.rs +++ b/trunk/trunk-registry/src/publish.rs @@ -33,7 +33,7 @@ pub async fn publish( while let Some(mut field) = payload.try_next().await? { let headers = field.headers(); let auth = headers.get(AUTHORIZATION).unwrap(); - if auth != "" { + if auth != cfg.auth_token { return Err(AuthorizationError()); } // Field is stream of Bytes