aboutsummaryrefslogtreecommitdiff
path: root/src/api/admin
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2022-05-11 11:40:26 +0200
committerAlex Auvolat <alex@adnab.me>2022-05-11 11:40:26 +0200
commit393b76ecba66ff11b80bf404691704568f2d1794 (patch)
tree66aa5010cb6391f52360396481b759e4187400e1 /src/api/admin
parent5c00c9fb46305b021b5fc45d7ae7b1e13b72030c (diff)
downloadgarage-393b76ecba66ff11b80bf404691704568f2d1794.tar.gz
garage-393b76ecba66ff11b80bf404691704568f2d1794.zip
Implement CreateKey, DeleteKey and rudimentary UpdateKey
Diffstat (limited to 'src/api/admin')
-rw-r--r--src/api/admin/api_server.rs5
-rw-r--r--src/api/admin/key.rs95
2 files changed, 89 insertions, 11 deletions
diff --git a/src/api/admin/api_server.rs b/src/api/admin/api_server.rs
index e44443ff..952f6a73 100644
--- a/src/api/admin/api_server.rs
+++ b/src/api/admin/api_server.rs
@@ -136,10 +136,15 @@ impl ApiHandler for AdminApiServer {
Endpoint::GetKeyInfo { id, search } => {
handle_get_key_info(&self.garage, id, search).await
}
+ Endpoint::CreateKey => handle_create_key(&self.garage, req).await,
+ Endpoint::UpdateKey { id } => handle_update_key(&self.garage, id, req).await,
+ Endpoint::DeleteKey { id } => handle_delete_key(&self.garage, id).await,
+ /*
_ => Err(Error::NotImplemented(format!(
"Admin endpoint {} not implemented yet",
endpoint.name()
))),
+ */
}
}
}
diff --git a/src/api/admin/key.rs b/src/api/admin/key.rs
index 224be6c1..7cfe3fce 100644
--- a/src/api/admin/key.rs
+++ b/src/api/admin/key.rs
@@ -1,16 +1,11 @@
use std::collections::HashMap;
-use std::net::SocketAddr;
use std::sync::Arc;
use hyper::{Body, Request, Response, StatusCode};
use serde::{Deserialize, Serialize};
-use garage_util::crdt::*;
-use garage_util::data::*;
use garage_util::error::Error as GarageError;
-use garage_rpc::layout::*;
-
use garage_table::*;
use garage_model::garage::Garage;
@@ -62,7 +57,7 @@ pub async fn handle_get_key_info(
.ok_or(Error::NoSuchKey)?
} else if let Some(search) = search {
garage
- .bucket_helper()
+ .key_helper()
.get_existing_matching_key(&search)
.await
.map_err(|_| Error::NoSuchKey)?
@@ -70,6 +65,84 @@ pub async fn handle_get_key_info(
unreachable!();
};
+ key_info_results(garage, key).await
+}
+
+pub async fn handle_create_key(
+ garage: &Arc<Garage>,
+ req: Request<Body>,
+) -> Result<Response<Body>, Error> {
+ let req = parse_json_body::<CreateKeyRequest>(req).await?;
+
+ let key = Key::new(&req.name);
+ garage.key_table.insert(&key).await?;
+
+ key_info_results(garage, key).await
+}
+
+#[derive(Deserialize)]
+struct CreateKeyRequest {
+ name: String,
+}
+
+pub async fn handle_update_key(
+ garage: &Arc<Garage>,
+ id: String,
+ req: Request<Body>,
+) -> Result<Response<Body>, Error> {
+ let req = parse_json_body::<UpdateKeyRequest>(req).await?;
+
+ let mut key = garage
+ .key_table
+ .get(&EmptyKey, &id)
+ .await?
+ .ok_or(Error::NoSuchKey)?;
+
+ let key_state = key.state.as_option_mut().ok_or(Error::NoSuchKey)?;
+
+ if let Some(new_name) = req.name {
+ key_state.name.update(new_name);
+ }
+ if let Some(allow) = req.allow {
+ if allow.create_bucket {
+ key_state.allow_create_bucket.update(true);
+ }
+ }
+ if let Some(deny) = req.deny {
+ if deny.create_bucket {
+ key_state.allow_create_bucket.update(false);
+ }
+ }
+
+ garage.key_table.insert(&key).await?;
+
+ key_info_results(garage, key).await
+}
+
+#[derive(Deserialize)]
+struct UpdateKeyRequest {
+ name: Option<String>,
+ allow: Option<KeyPerm>,
+ deny: Option<KeyPerm>,
+}
+
+pub async fn handle_delete_key(garage: &Arc<Garage>, id: String) -> Result<Response<Body>, Error> {
+ let mut key = garage
+ .key_table
+ .get(&EmptyKey, &id)
+ .await?
+ .ok_or(Error::NoSuchKey)?;
+
+ key.state.as_option().ok_or(Error::NoSuchKey)?;
+
+ garage.key_helper().delete_key(&mut key).await?;
+
+ Ok(Response::builder()
+ .status(StatusCode::NO_CONTENT)
+ .body(Body::empty())?)
+}
+
+async fn key_info_results(garage: &Arc<Garage>, key: Key) -> Result<Response<Body>, Error> {
let mut relevant_buckets = HashMap::new();
let key_state = key.state.as_option().unwrap();
@@ -99,7 +172,7 @@ pub async fn handle_get_key_info(
name: key_state.name.get().clone(),
access_key_id: key.key_id.clone(),
secret_access_key: key_state.secret_key.clone(),
- permissions: KeyPermResult {
+ permissions: KeyPerm {
create_bucket: *key_state.allow_create_bucket.get(),
},
buckets: relevant_buckets
@@ -153,13 +226,13 @@ struct GetKeyInfoResult {
access_key_id: String,
#[serde(rename = "secretAccessKey")]
secret_access_key: String,
- permissions: KeyPermResult,
+ permissions: KeyPerm,
buckets: Vec<KeyInfoBucketResult>,
}
-#[derive(Serialize)]
-struct KeyPermResult {
- #[serde(rename = "createBucket")]
+#[derive(Serialize, Deserialize)]
+struct KeyPerm {
+ #[serde(rename = "createBucket", default)]
create_bucket: bool,
}