Specify and implement {Global,Local}{Alias,Unalias}Bucket
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing

This commit is contained in:
Alex 2022-05-17 17:16:29 +02:00
parent e92c52eb65
commit 2ce3513c10
Signed by: lx
GPG key ID: 0E496D15096376BE
4 changed files with 133 additions and 9 deletions

View file

@ -501,3 +501,22 @@ Request body format:
Flags in `permissions` which have the value `true` will be deactivated. Flags in `permissions` which have the value `true` will be deactivated.
Other flags will remain unchanged. Other flags will remain unchanged.
## Operations on bucket aliases
### GlobalAliasBucket `PUT /bucket/alias/global?id=<bucket id>&alias=<global alias>`
Empty body. Creates a global alias for a bucket.
### GlobalUnaliasBucket `DELETE /bucket/alias/global?id=<bucket id>&alias=<global alias>`
Removes a global alias for a bucket.
### LocalAliasBucket `PUT /bucket/alias/local?id=<bucket id>&accessKeyId=<access key ID>&alias=<local alias>`
Empty body. Creates a local alias for a bucket in the namespace of a specific access key.
### LocalUnaliasBucket `DELETE /bucket/alias/local?id=<bucket id>&accessKeyId<access key ID>&alias=<local alias>`
Removes a local alias for a bucket in the namespace of a specific access key.

View file

@ -151,6 +151,23 @@ impl ApiHandler for AdminApiServer {
Endpoint::BucketDenyKey => { Endpoint::BucketDenyKey => {
handle_bucket_change_key_perm(&self.garage, req, false).await handle_bucket_change_key_perm(&self.garage, req, false).await
} }
// Bucket aliasing
Endpoint::GlobalAliasBucket { id, alias } => {
handle_global_alias_bucket(&self.garage, id, alias).await
}
Endpoint::GlobalUnaliasBucket { id, alias } => {
handle_global_unalias_bucket(&self.garage, id, alias).await
}
Endpoint::LocalAliasBucket {
id,
access_key_id,
alias,
} => handle_local_alias_bucket(&self.garage, id, access_key_id, alias).await,
Endpoint::LocalUnaliasBucket {
id,
access_key_id,
alias,
} => handle_local_unalias_bucket(&self.garage, id, access_key_id, alias).await,
} }
} }
} }

View file

@ -87,10 +87,7 @@ pub async fn handle_get_bucket_info(
global_alias: Option<String>, global_alias: Option<String>,
) -> Result<Response<Body>, Error> { ) -> Result<Response<Body>, Error> {
let bucket_id = match (id, global_alias) { let bucket_id = match (id, global_alias) {
(Some(id), None) => { (Some(id), None) => parse_bucket_id(&id)?,
let id_hex = hex::decode(&id).ok_or_bad_request("Invalid bucket id")?;
Uuid::try_from(&id_hex).ok_or_bad_request("Invalid bucket id")?
}
(None, Some(ga)) => garage (None, Some(ga)) => garage
.bucket_helper() .bucket_helper()
.resolve_global_bucket_name(&ga) .resolve_global_bucket_name(&ga)
@ -324,8 +321,7 @@ pub async fn handle_delete_bucket(
) -> Result<Response<Body>, Error> { ) -> Result<Response<Body>, Error> {
let helper = garage.bucket_helper(); let helper = garage.bucket_helper();
let id_hex = hex::decode(&id).ok_or_bad_request("Invalid bucket id")?; let bucket_id = parse_bucket_id(&id)?;
let bucket_id = Uuid::try_from(&id_hex).ok_or_bad_request("Invalid bucket id")?;
let mut bucket = helper.get_existing_bucket(bucket_id).await?; let mut bucket = helper.get_existing_bucket(bucket_id).await?;
let state = bucket.state.as_option().unwrap(); let state = bucket.state.as_option().unwrap();
@ -385,8 +381,7 @@ pub async fn handle_bucket_change_key_perm(
) -> Result<Response<Body>, Error> { ) -> Result<Response<Body>, Error> {
let req = parse_json_body::<BucketKeyPermChangeRequest>(req).await?; let req = parse_json_body::<BucketKeyPermChangeRequest>(req).await?;
let id_hex = hex::decode(&req.bucket_id).ok_or_bad_request("Invalid bucket id")?; let bucket_id = parse_bucket_id(&req.bucket_id)?;
let bucket_id = Uuid::try_from(&id_hex).ok_or_bad_request("Invalid bucket id")?;
let bucket = garage let bucket = garage
.bucket_helper() .bucket_helper()
@ -430,3 +425,70 @@ struct BucketKeyPermChangeRequest {
access_key_id: String, access_key_id: String,
permissions: ApiBucketKeyPerm, permissions: ApiBucketKeyPerm,
} }
pub async fn handle_global_alias_bucket(
garage: &Arc<Garage>,
bucket_id: String,
alias: String,
) -> Result<Response<Body>, Error> {
let bucket_id = parse_bucket_id(&bucket_id)?;
garage
.bucket_helper()
.set_global_bucket_alias(bucket_id, &alias)
.await?;
bucket_info_results(garage, bucket_id).await
}
pub async fn handle_global_unalias_bucket(
garage: &Arc<Garage>,
bucket_id: String,
alias: String,
) -> Result<Response<Body>, Error> {
let bucket_id = parse_bucket_id(&bucket_id)?;
garage
.bucket_helper()
.unset_global_bucket_alias(bucket_id, &alias)
.await?;
bucket_info_results(garage, bucket_id).await
}
pub async fn handle_local_alias_bucket(
garage: &Arc<Garage>,
bucket_id: String,
access_key_id: String,
alias: String,
) -> Result<Response<Body>, Error> {
let bucket_id = parse_bucket_id(&bucket_id)?;
garage
.bucket_helper()
.set_local_bucket_alias(bucket_id, &access_key_id, &alias)
.await?;
bucket_info_results(garage, bucket_id).await
}
pub async fn handle_local_unalias_bucket(
garage: &Arc<Garage>,
bucket_id: String,
access_key_id: String,
alias: String,
) -> Result<Response<Body>, Error> {
let bucket_id = parse_bucket_id(&bucket_id)?;
garage
.bucket_helper()
.unset_local_bucket_alias(bucket_id, &access_key_id, &alias)
.await?;
bucket_info_results(garage, bucket_id).await
}
fn parse_bucket_id(id: &str) -> Result<Uuid, Error> {
let id_hex = hex::decode(&id).ok_or_bad_request("Invalid bucket id")?;
Ok(Uuid::try_from(&id_hex).ok_or_bad_request("Invalid bucket id")?)
}

View file

@ -49,6 +49,25 @@ pub enum Endpoint {
// Bucket-Key Permissions // Bucket-Key Permissions
BucketAllowKey, BucketAllowKey,
BucketDenyKey, BucketDenyKey,
// Bucket aliases
GlobalAliasBucket {
id: String,
alias: String,
},
GlobalUnaliasBucket {
id: String,
alias: String,
},
LocalAliasBucket {
id: String,
access_key_id: String,
alias: String,
},
LocalUnaliasBucket {
id: String,
access_key_id: String,
alias: String,
},
}} }}
impl Endpoint { impl Endpoint {
@ -87,6 +106,11 @@ impl Endpoint {
// Bucket-key permissions // Bucket-key permissions
POST "/bucket/allow" => BucketAllowKey, POST "/bucket/allow" => BucketAllowKey,
POST "/bucket/deny" => BucketDenyKey, POST "/bucket/deny" => BucketDenyKey,
// Bucket aliases
PUT "/bucket/alias/global" => GlobalAliasBucket (query::id, query::alias),
DELETE "/bucket/alias/global" => GlobalUnaliasBucket (query::id, query::alias),
PUT "/bucket/alias/local" => LocalAliasBucket (query::id, query::access_key_id, query::alias),
DELETE "/bucket/alias/local" => LocalUnaliasBucket (query::id, query::access_key_id, query::alias),
]); ]);
if let Some(message) = query.nonempty_message() { if let Some(message) = query.nonempty_message() {
@ -107,5 +131,7 @@ impl Endpoint {
generateQueryParameters! { generateQueryParameters! {
"id" => id, "id" => id,
"search" => search, "search" => search,
"globalAlias" => global_alias "globalAlias" => global_alias,
"alias" => alias,
"accessKeyId" => access_key_id
} }