diff options
author | Ilion Beyst <ilion.beyst@gmail.com> | 2022-06-19 22:33:44 +0200 |
---|---|---|
committer | Ilion Beyst <ilion.beyst@gmail.com> | 2022-06-19 22:34:01 +0200 |
commit | 478094abcf6f79ddb4e13e5763f5827208363ae7 (patch) | |
tree | c17d32bc7d48ff0c6f313dad53dac92c32a6c86c /planetwars-server/src | |
parent | 2cde7ec673b38b51db0dce8d5e8496ba2d92aa12 (diff) | |
download | planetwars.dev-478094abcf6f79ddb4e13e5763f5827208363ae7.tar.xz planetwars.dev-478094abcf6f79ddb4e13e5763f5827208363ae7.zip |
basic docker login PoC
Diffstat (limited to 'planetwars-server/src')
-rw-r--r-- | planetwars-server/src/modules/registry.rs | 57 |
1 files changed, 42 insertions, 15 deletions
diff --git a/planetwars-server/src/modules/registry.rs b/planetwars-server/src/modules/registry.rs index 6095527..9d71dd7 100644 --- a/planetwars-server/src/modules/registry.rs +++ b/planetwars-server/src/modules/registry.rs @@ -1,9 +1,11 @@ -use axum::body::{Body, StreamBody}; -use axum::extract::{BodyStream, Path, Query}; +use axum::body::{Body, Bytes, StreamBody}; +use axum::extract::{BodyStream, FromRequest, Path, Query, RequestParts, TypedHeader}; use axum::handler::Handler; +use axum::headers::authorization::Basic; +use axum::headers::Authorization; use axum::response::{IntoResponse, Response}; use axum::routing::{get, head, post, put}; -use axum::Router; +use axum::{async_trait, Router}; use hyper::StatusCode; use serde::Serialize; use sha2::{Digest, Sha256}; @@ -16,7 +18,8 @@ use crate::util::gen_alphanumeric; const REGISTRY_PATH: &'static str = "./data/registry"; pub fn registry_service() -> Router { Router::new() - .nest("/v2", registry_api_v2()) + // The docker API requires this trailing slash + .nest("/v2/", registry_api_v2()) .fallback(fallback.into_service()) } @@ -41,8 +44,41 @@ async fn fallback(request: axum::http::Request<Body>) -> impl IntoResponse { StatusCode::NOT_FOUND } -// root should return 200 OK to confirm api compliance -async fn root_handler() -> Response<Body> { +type AuthorizationHeader = TypedHeader<Authorization<Basic>>; + +struct RegistryAuth; + +#[async_trait] +impl<B> FromRequest<B> for RegistryAuth +where + B: Send, +{ + type Rejection = Response<axum::body::Full<Bytes>>; + + async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> { + let TypedHeader(Authorization(_basic)) = + AuthorizationHeader::from_request(req).await.map_err(|_| { + let err = RegistryErrors { + errors: vec![RegistryError { + code: "UNAUTHORIZED".to_string(), + message: "please log in".to_string(), + detail: serde_json::Value::Null, + }], + }; + Response::builder() + .status(StatusCode::UNAUTHORIZED) + .header("Docker-Distribution-API-Version", "registry/2.0") + .header("WWW-Authenticate", "Basic") + .body(axum::body::Full::from(serde_json::to_vec(&err).unwrap())) + .unwrap() + })?; + + Ok(RegistryAuth) + } +} + +async fn root_handler(_auth: RegistryAuth) -> impl IntoResponse { + // root should return 200 OK to confirm api compliance Response::builder() .status(StatusCode::OK) .header("Docker-Distribution-API-Version", "registry/2.0") @@ -89,15 +125,6 @@ async fn get_blob( } async fn blob_upload(Path(repository_name): Path<String>) -> impl IntoResponse { - // let value = json!({ - // "errors": [ - // { - // "code": "UNSUPPORTED", - // "message": "not implemented yet lol", - // } - // ] - // }); - let uuid = gen_alphanumeric(16); tokio::fs::File::create(PathBuf::from(REGISTRY_PATH).join("uploads").join(&uuid)) .await |