From d137b62fc21765c2efb2f8f6410f1bae70e046b8 Mon Sep 17 00:00:00 2001 From: Oriol Torrillas Date: Mon, 8 Jun 2026 17:27:21 +0200 Subject: [PATCH] feat(auth): add datastore and connection OAuth scopes Add datastore read/write/manage scopes and connection write scope to the default OAuth login scope set, while keeping read-only login constrained to read scopes. Allow workflow action connection commands to send OAuth bearer tokens now that the connection scopes are requested, and update the command help accordingly. --- src/auth/types.rs | 20 +++++++++++++++++++- src/commands/workflows.rs | 16 ++++++++++++---- src/main.rs | 5 ++--- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/auth/types.rs b/src/auth/types.rs index a2e86eb..0b5db4c 100644 --- a/src/auth/types.rs +++ b/src/auth/types.rs @@ -51,6 +51,7 @@ pub fn read_only_scopes() -> Vec<&'static str> { "apm_read", "apm_service_catalog_read", "apps_run", + "apps_datastore_read", "audit_logs_read", "aws_configuration_read", "azure_configuration_read", @@ -99,6 +100,7 @@ pub fn read_only_scopes() -> Vec<&'static str> { "usage_read", "user_access_read", "workflows_read", + "connections_read", ] } @@ -112,8 +114,13 @@ pub fn default_scopes() -> Vec<&'static str> { // App Builder "apps_run", "apps_write", - // Connections (required by App Builder GetApp) + // Datastores + "apps_datastore_read", + "apps_datastore_write", + "apps_datastore_manage", + // Connections (required by App Builder and Workflow Automation) "connections_read", + "connections_write", // Audit "audit_logs_read", // AWS @@ -317,7 +324,13 @@ mod tests { // App Builder assert!(scopes.contains(&"apps_run")); assert!(scopes.contains(&"apps_write")); + // Datastores + assert!(scopes.contains(&"apps_datastore_read")); + assert!(scopes.contains(&"apps_datastore_write")); + assert!(scopes.contains(&"apps_datastore_manage")); + // Connections assert!(scopes.contains(&"connections_read")); + assert!(scopes.contains(&"connections_write")); } #[test] @@ -334,6 +347,11 @@ mod tests { assert!(ro.contains(&"dashboards_read")); assert!(ro.contains(&"monitors_read")); assert!(ro.contains(&"apps_run")); + assert!(ro.contains(&"apps_datastore_read")); + assert!(ro.contains(&"connections_read")); + assert!(!ro.contains(&"apps_datastore_write")); + assert!(!ro.contains(&"apps_datastore_manage")); + assert!(!ro.contains(&"connections_write")); assert!(!ro.contains(&"org_management")); assert!(!ro.contains(&"teams_manage")); assert!(!ro.contains(&"monitors_write")); diff --git a/src/commands/workflows.rs b/src/commands/workflows.rs index 9a7f8ca..2657d80 100644 --- a/src/commands/workflows.rs +++ b/src/commands/workflows.rs @@ -215,7 +215,7 @@ pub async fn instance_cancel(cfg: &Config, workflow_id: &str, instance_id: &str) // --------------------------------------------------------------------------- fn make_connection_api(cfg: &Config) -> ActionConnectionAPI { - crate::make_api_no_auth!(ActionConnectionAPI, cfg) + crate::make_api!(ActionConnectionAPI, cfg) } pub async fn connections_get(cfg: &Config, connection_id: &str) -> Result<()> { @@ -260,7 +260,6 @@ pub async fn connections_delete(cfg: &Config, connection_id: &str) -> Result<()> #[cfg(test)] mod tests { - use crate::test_support::*; #[tokio::test] @@ -268,8 +267,17 @@ mod tests { let _lock = lock_env().await; std::env::set_var("DD_TOKEN_STORAGE", "file"); let mut server = mockito::Server::new_async().await; - let cfg = test_config(&server.url()); - let _mock = mock_any(&mut server, "GET", r#"{}"#).await; + let mut cfg = test_config(&server.url()); + cfg.access_token = Some("oauth-bearer-token".into()); + let _mock = server + .mock("GET", mockito::Matcher::Any) + .match_query(mockito::Matcher::Any) + .match_header("Authorization", "Bearer oauth-bearer-token") + .with_status(200) + .with_header("content-type", "application/json") + .with_body(r#"{}"#) + .create_async() + .await; let result = super::connections_get(&cfg, "conn-id").await; assert!(result.is_ok(), "connections get failed: {:?}", result.err()); cleanup_env(); diff --git a/src/main.rs b/src/main.rs index 73f8985..3e31271 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2757,9 +2757,8 @@ enum Commands { /// Workflow CRUD (`workflows get/create/update/delete`), /// `workflows run`, and `workflows instances *` accept OAuth2 /// (`pup auth login`) or DD_API_KEY + DD_APP_KEY. - /// `workflows connections *` requires DD_API_KEY + DD_APP_KEY - /// pending server-side OAuth enablement on the action-connections - /// API. + /// `workflows connections *` accepts OAuth2 with connections_read / + /// connections_write scopes, or DD_API_KEY + DD_APP_KEY. #[command(verbatim_doc_comment)] Workflows { #[command(subcommand)]