more complete admin API #298
6 changed files with 53 additions and 5 deletions
|
@ -273,6 +273,20 @@ Request body format:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### ImportKey `POST /v0/key/import`
|
||||||
|
|
||||||
|
Imports an existing API key.
|
||||||
|
|
||||||
|
Request body format:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"accessKeyId": "GK31c2f218a2e44f485b94239e",
|
||||||
|
"secretAccessKey": "b892c0665f0ada8a4755dae98baa3b133590e11dae3bcc1f9d769d67f16c3835",
|
||||||
|
"name": "NameOfMyKey"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### GetKeyInfo `GET /v0/key?id=<acces key id>`
|
### GetKeyInfo `GET /v0/key?id=<acces key id>`
|
||||||
### GetKeyInfo `GET /v0/key?search=<pattern>`
|
### GetKeyInfo `GET /v0/key?search=<pattern>`
|
||||||
|
|
||||||
|
|
|
@ -136,6 +136,7 @@ impl ApiHandler for AdminApiServer {
|
||||||
handle_get_key_info(&self.garage, id, search).await
|
handle_get_key_info(&self.garage, id, search).await
|
||||||
}
|
}
|
||||||
Endpoint::CreateKey => handle_create_key(&self.garage, req).await,
|
Endpoint::CreateKey => handle_create_key(&self.garage, req).await,
|
||||||
|
Endpoint::ImportKey => handle_import_key(&self.garage, req).await,
|
||||||
Endpoint::UpdateKey { id } => handle_update_key(&self.garage, id, req).await,
|
Endpoint::UpdateKey { id } => handle_update_key(&self.garage, id, req).await,
|
||||||
Endpoint::DeleteKey { id } => handle_delete_key(&self.garage, id).await,
|
Endpoint::DeleteKey { id } => handle_delete_key(&self.garage, id).await,
|
||||||
// Buckets
|
// Buckets
|
||||||
|
|
|
@ -20,6 +20,13 @@ pub enum Error {
|
||||||
/// The API access key does not exist
|
/// The API access key does not exist
|
||||||
#[error(display = "Access key not found: {}", _0)]
|
#[error(display = "Access key not found: {}", _0)]
|
||||||
NoSuchAccessKey(String),
|
NoSuchAccessKey(String),
|
||||||
|
|
||||||
|
/// In Import key, the key already exists
|
||||||
|
#[error(
|
||||||
|
display = "Key {} already exists in data store. Even if it is deleted, we can't let you create a new key with the same ID. Sorry.",
|
||||||
|
_0
|
||||||
|
)]
|
||||||
|
KeyAlreadyExists(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> From<T> for Error
|
impl<T> From<T> for Error
|
||||||
|
@ -52,6 +59,7 @@ impl Error {
|
||||||
match self {
|
match self {
|
||||||
Error::CommonError(c) => c.aws_code(),
|
Error::CommonError(c) => c.aws_code(),
|
||||||
Error::NoSuchAccessKey(_) => "NoSuchAccessKey",
|
Error::NoSuchAccessKey(_) => "NoSuchAccessKey",
|
||||||
|
Error::KeyAlreadyExists(_) => "KeyAlreadyExists",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,6 +70,7 @@ impl ApiError for Error {
|
||||||
match self {
|
match self {
|
||||||
Error::CommonError(c) => c.http_status_code(),
|
Error::CommonError(c) => c.http_status_code(),
|
||||||
Error::NoSuchAccessKey(_) => StatusCode::NOT_FOUND,
|
Error::NoSuchAccessKey(_) => StatusCode::NOT_FOUND,
|
||||||
|
Error::KeyAlreadyExists(_) => StatusCode::CONFLICT,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,31 @@ struct CreateKeyRequest {
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn handle_import_key(
|
||||||
|
garage: &Arc<Garage>,
|
||||||
|
req: Request<Body>,
|
||||||
|
) -> Result<Response<Body>, Error> {
|
||||||
|
let req = parse_json_body::<ImportKeyRequest>(req).await?;
|
||||||
|
|
||||||
|
let prev_key = garage.key_table.get(&EmptyKey, &req.access_key_id).await?;
|
||||||
|
if prev_key.is_some() {
|
||||||
|
return Err(Error::KeyAlreadyExists(req.access_key_id.to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let imported_key = Key::import(&req.access_key_id, &req.secret_access_key, &req.name);
|
||||||
|
garage.key_table.insert(&imported_key).await?;
|
||||||
|
|
||||||
|
key_info_results(garage, imported_key).await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
struct ImportKeyRequest {
|
||||||
|
access_key_id: String,
|
||||||
|
secret_access_key: String,
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn handle_update_key(
|
pub async fn handle_update_key(
|
||||||
garage: &Arc<Garage>,
|
garage: &Arc<Garage>,
|
||||||
id: String,
|
id: String,
|
||||||
|
|
|
@ -27,6 +27,7 @@ pub enum Endpoint {
|
||||||
// Keys
|
// Keys
|
||||||
ListKeys,
|
ListKeys,
|
||||||
CreateKey,
|
CreateKey,
|
||||||
|
ImportKey,
|
||||||
GetKeyInfo {
|
GetKeyInfo {
|
||||||
id: Option<String>,
|
id: Option<String>,
|
||||||
search: Option<String>,
|
search: Option<String>,
|
||||||
|
@ -103,6 +104,7 @@ impl Endpoint {
|
||||||
GET "/v0/key" if search => GetKeyInfo (query_opt::id, query_opt::search),
|
GET "/v0/key" if search => GetKeyInfo (query_opt::id, query_opt::search),
|
||||||
POST "/v0/key" if id => UpdateKey (query::id),
|
POST "/v0/key" if id => UpdateKey (query::id),
|
||||||
POST "/v0/key" => CreateKey,
|
POST "/v0/key" => CreateKey,
|
||||||
|
POST "/v0/key/import" => ImportKey,
|
||||||
DELETE "/v0/key" if id => DeleteKey (query::id),
|
DELETE "/v0/key" if id => DeleteKey (query::id),
|
||||||
GET "/v0/key" => ListKeys,
|
GET "/v0/key" => ListKeys,
|
||||||
// Bucket endpoints
|
// Bucket endpoints
|
||||||
|
|
|
@ -384,12 +384,9 @@ impl System {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if errors.len() == 1 {
|
if errors.len() == 1 {
|
||||||
return Err(Error::Message(errors[0].1.to_string()));
|
Err(Error::Message(errors[0].1.to_string()))
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::Message(format!(
|
Err(Error::Message(format!("{:?}", errors)))
|
||||||
"Could not connect to specified peers. Errors: {:?}",
|
|
||||||
errors
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue