From 70b36eb47a7c9e61493551a7167a5437217fb75d Mon Sep 17 00:00:00 2001 From: Jack Westwood Date: Wed, 5 Feb 2025 09:17:03 +0000 Subject: [PATCH] Allow resources to be specified when creating cluster credentials --- src/cli/credentials_create.rs | 59 +++++++++++++++++++++++++++++++++-- src/client/cloud_json.rs | 15 ++++++--- 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/src/cli/credentials_create.rs b/src/cli/credentials_create.rs index 3d96dca0..b5fe057b 100644 --- a/src/cli/credentials_create.rs +++ b/src/cli/credentials_create.rs @@ -8,7 +8,7 @@ use crate::state::State; use nu_engine::command_prelude::Call; use nu_engine::CallExt; use nu_protocol::engine::{Command, EngineState, Stack}; -use nu_protocol::{Category, PipelineData, ShellError, Signature, SyntaxShape}; +use nu_protocol::{Category, PipelineData, ShellError, Signature, SyntaxShape, Value}; use std::sync::{Arc, Mutex}; #[derive(Clone)] @@ -53,6 +53,16 @@ impl Command for CredentialsCreate { SyntaxShape::String, "the clusters which should be contacted", None, + ).named( + "bucket", + SyntaxShape::String, + "the bucket the created credentials have access to, leave empty to allow access to all buckets", + None, + ).named( + "scopes", + SyntaxShape::List(Box::new(SyntaxShape::String)), + "the scopes the created credentials have access to, leave empty to allow access to all scopes", + None, ) } @@ -84,6 +94,44 @@ fn credentials_create( let read = call.has_flag(engine_state, stack, "read")?; let write = call.has_flag(engine_state, stack, "write")?; let use_registered = call.has_flag(engine_state, stack, "registered")?; + let bucket = call.get_flag(engine_state, stack, "bucket")?; + let scopes_flag: Option = call.get_flag(engine_state, stack, "scopes")?; + + let scopes = if let Some(scopes) = scopes_flag { + if bucket.is_none() { + return Err(ShellError::GenericError { + error: "--scopes cannot be used without specifying a bucket".to_string(), + msg: "".to_string(), + span: None, + help: Some( + "Use the --bucket flag to specify a bucket the credentials are allowed to access" + .to_string(), + ), + inner: vec![], + }); + } + + match scopes { + Value::String { val, .. } => { + Ok(vec!(val)) + }, + Value::List { vals, .. } => { + vals.iter().map(|v| v.as_str().map(|s| s.to_string())).collect() + } + _ => Err(ShellError::GenericError { + error: "--scopes cannot be used without specifying a bucket".to_string(), + msg: "".to_string(), + span: None, + help: Some( + "Use the --bucket flag to specify a bucket the credentials are allowed to access" + .to_string(), + ), + inner: vec![], + }) + }? + } else { + vec!["*".to_string()] + }; if !read && !write { return Err(ShellError::GenericError { @@ -144,7 +192,14 @@ fn credentials_create( get_username_and_password(username_flag, password_flag)? }; - let payload = CredentialsCreateRequest::new(name.clone(), password.clone(), read, write); + let payload = CredentialsCreateRequest::new( + name.clone(), + password.clone(), + read, + write, + bucket.clone(), + scopes.clone(), + ); client .create_credentials( diff --git a/src/client/cloud_json.rs b/src/client/cloud_json.rs index 60aed3ab..20ce5606 100644 --- a/src/client/cloud_json.rs +++ b/src/client/cloud_json.rs @@ -537,7 +537,14 @@ struct Bucket { } impl CredentialsCreateRequest { - pub fn new(name: String, password: String, read: bool, write: bool) -> Self { + pub fn new( + name: String, + password: String, + read: bool, + write: bool, + bucket: Option, + scopes: Vec, + ) -> Self { let mut privileges = vec![]; if read { @@ -555,10 +562,8 @@ impl CredentialsCreateRequest { privileges, resources: Resources { buckets: vec![Bucket { - name: "*".to_string(), - scopes: Some(vec![Scope { - name: "*".to_string(), - }]), + name: bucket.unwrap_or("*".to_string()), + scopes: Some(scopes.iter().map(|s| Scope { name: s.into() }).collect()), }], }, }],