Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 89 additions & 30 deletions src/auth/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,55 +42,104 @@ pub struct ClientCredentials {
/// Default OAuth scopes requested during login.
pub fn default_scopes() -> Vec<&'static str> {
vec![
// APM
"apm_read",
"apm_service_catalog_read",
// Audit
"audit_logs_read",
// Azure
"azure_configuration_read",
// BITS
"bits_investigations_read",
"bits_investigations_write",
// Cases
"cases_read",
"cases_write",
// CI Visibility
"ci_visibility_read",
"code_coverage_read",
"dora_metrics_write",
"test_optimization_read",
"test_optimization_write",
// Dashboards
"dashboards_read",
"dashboards_write",
// Data Scanner
"data_scanner_read",
// Error Tracking
"error_tracking_read",
"monitors_read",
"monitors_write",
"monitors_downtime",
"audit_logs_read",
"apm_read",
"slos_read",
"slos_write",
"slos_corrections",
// Events
"events_read",
// HAMR (disaster recovery)
"disaster_recovery_status_read",
"disaster_recovery_status_write",
// Hosts
"hosts_read",
"host_tags_write",
// Incidents
"incident_read",
"incident_write",
"incident_notification_settings_read",
"incident_settings_read",
"incident_settings_write",
"synthetics_read",
"synthetics_write",
"synthetics_global_variable_read",
"synthetics_global_variable_write",
"synthetics_private_location_read",
"synthetics_private_location_write",
"security_monitoring_signals_read",
"security_monitoring_rules_read",
"security_monitoring_findings_read",
"security_monitoring_suppressions_read",
"security_monitoring_filters_read",
"rum_apps_read",
"rum_apps_write",
"rum_retention_filters_read",
"rum_retention_filters_write",
"hosts_read",
"user_access_read",
"user_self_profile_read",
"cases_read",
"cases_write",
"events_read",
// Integrations (Jira, ServiceNow, Slack, Webhooks)
"integrations_read",
"manage_integrations",
// Logs
"logs_generate_metrics",
"logs_modify_indexes",
"logs_read_archives",
"logs_read_config",
"logs_read_data",
"logs_read_index_data",
"logs_write_archives",
// Metrics
"metrics_read",
// Monitors
"monitors_read",
"monitors_write",
"monitors_downtime",
// Notebooks
"notebooks_read",
"notebooks_write",
// OCI
"oci_configuration_edit",
"oci_configuration_read",
"oci_configurations_manage",
// Organizations
"org_management",
// RUM
"rum_apps_read",
"rum_apps_write",
"rum_generate_metrics",
"rum_retention_filters_read",
"rum_retention_filters_write",
"rum_session_replay_read",
// Security
"security_monitoring_filters_read",
"security_monitoring_filters_write",
"security_monitoring_findings_read",
"security_monitoring_rules_read",
"security_monitoring_rules_write",
"security_monitoring_signals_read",
// SLOs
"slos_read",
"slos_write",
// Status Pages
"status_pages_settings_read",
"status_pages_settings_write",
// Synthetics
"synthetics_read",
"synthetics_write",
"synthetics_private_location_read",
// Teams
"teams_read",
// Timeseries
"timeseries_query",
// Usage
"usage_read",
// Users
"user_access_read",
]
}

Expand Down Expand Up @@ -137,10 +186,20 @@ mod tests {
#[test]
fn test_default_scopes() {
let scopes = default_scopes();
assert!(scopes.len() > 20);
assert_eq!(scopes.len(), 69);
assert!(scopes.contains(&"dashboards_read"));
assert!(scopes.contains(&"monitors_read"));
assert!(scopes.contains(&"logs_read_data"));
// Batch 2 additions
assert!(scopes.contains(&"integrations_read"));
assert!(scopes.contains(&"org_management"));
assert!(scopes.contains(&"disaster_recovery_status_read"));
assert!(scopes.contains(&"notebooks_read"));
assert!(scopes.contains(&"rum_generate_metrics"));
assert!(scopes.contains(&"ci_visibility_read"));
assert!(scopes.contains(&"teams_read"));
assert!(scopes.contains(&"apm_service_catalog_read"));
assert!(scopes.contains(&"status_pages_settings_read"));
}

#[test]
Expand Down
98 changes: 17 additions & 81 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,47 +264,6 @@ fn find_endpoint_requirement(method: &str, path: &str) -> Option<&'static Endpoi
/// Trailing "/" means prefix match for ID-parameterized paths.
#[cfg(not(target_arch = "wasm32"))]
static OAUTH_EXCLUDED_ENDPOINTS: &[EndpointRequirement] = &[
// RUM API (10)
EndpointRequirement {
path: "/api/v2/rum/applications",
method: "GET",
},
EndpointRequirement {
path: "/api/v2/rum/applications/",
method: "GET",
},
EndpointRequirement {
path: "/api/v2/rum/applications",
method: "POST",
},
EndpointRequirement {
path: "/api/v2/rum/applications/",
method: "PATCH",
},
EndpointRequirement {
path: "/api/v2/rum/applications/",
method: "DELETE",
},
EndpointRequirement {
path: "/api/v2/rum/metrics",
method: "GET",
},
EndpointRequirement {
path: "/api/v2/rum/metrics/",
method: "GET",
},
EndpointRequirement {
path: "/api/v2/rum/retention_filters",
method: "GET",
},
EndpointRequirement {
path: "/api/v2/rum/retention_filters/",
method: "GET",
},
EndpointRequirement {
path: "/api/v2/rum/events/search",
method: "POST",
},
// API/App Keys (8)
EndpointRequirement {
path: "/api/v2/api_keys",
Expand Down Expand Up @@ -342,11 +301,6 @@ static OAUTH_EXCLUDED_ENDPOINTS: &[EndpointRequirement] = &[
path: "/api/v2/application_keys/",
method: "DELETE",
},
// Events (1)
EndpointRequirement {
path: "/api/v2/events/search",
method: "POST",
},
// Fleet Automation (15)
EndpointRequirement {
path: "/api/v2/fleet/agents",
Expand Down Expand Up @@ -408,27 +362,6 @@ static OAUTH_EXCLUDED_ENDPOINTS: &[EndpointRequirement] = &[
path: "/api/v2/fleet/schedules/",
method: "POST",
},
// Notebooks (5)
EndpointRequirement {
path: "/api/v1/notebooks",
method: "GET",
},
EndpointRequirement {
path: "/api/v1/notebooks",
method: "POST",
},
EndpointRequirement {
path: "/api/v1/notebooks/",
method: "GET",
},
EndpointRequirement {
path: "/api/v1/notebooks/",
method: "PUT",
},
EndpointRequirement {
path: "/api/v1/notebooks/",
method: "DELETE",
},
];

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -557,17 +490,20 @@ mod tests {
}

#[test]
fn test_requires_api_key_fallback_rum() {
assert!(requires_api_key_fallback("GET", "/api/v2/rum/applications"));
assert!(requires_api_key_fallback(
fn test_no_fallback_for_rum() {
assert!(!requires_api_key_fallback(
"GET",
"/api/v2/rum/applications"
));
assert!(!requires_api_key_fallback(
"GET",
"/api/v2/rum/applications/abc-123"
));
}

#[test]
fn test_requires_api_key_fallback_events() {
assert!(requires_api_key_fallback("POST", "/api/v2/events/search"));
fn test_no_fallback_for_events_search() {
assert!(!requires_api_key_fallback("POST", "/api/v2/events/search"));
}

#[test]
Expand All @@ -580,14 +516,14 @@ mod tests {
#[test]
fn test_prefix_matching_with_id() {
// Trailing "/" in the pattern should match paths with IDs
assert!(requires_api_key_fallback(
"GET",
"/api/v2/rum/applications/some-uuid-here"
));
assert!(requires_api_key_fallback(
"DELETE",
"/api/v2/api_keys/key-123"
));
assert!(requires_api_key_fallback(
"GET",
"/api/v2/fleet/agents/agent-123"
));
}

#[test]
Expand All @@ -606,7 +542,7 @@ mod tests {

#[test]
fn test_oauth_excluded_count() {
assert_eq!(OAUTH_EXCLUDED_ENDPOINTS.len(), 40);
assert_eq!(OAUTH_EXCLUDED_ENDPOINTS.len(), 24);
}

#[test]
Expand Down Expand Up @@ -675,10 +611,10 @@ mod tests {
}

#[test]
fn test_requires_api_key_fallback_notebooks() {
assert!(requires_api_key_fallback("GET", "/api/v1/notebooks"));
assert!(requires_api_key_fallback("GET", "/api/v1/notebooks/12345"));
assert!(requires_api_key_fallback("POST", "/api/v1/notebooks"));
fn test_no_fallback_for_notebooks() {
assert!(!requires_api_key_fallback("GET", "/api/v1/notebooks"));
assert!(!requires_api_key_fallback("GET", "/api/v1/notebooks/12345"));
assert!(!requires_api_key_fallback("POST", "/api/v1/notebooks"));
}

#[test]
Expand Down
15 changes: 5 additions & 10 deletions src/commands/events.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use anyhow::{bail, Result};
use anyhow::Result;
#[cfg(not(target_arch = "wasm32"))]
use datadog_api_client::datadogV1::api_events::{
EventsAPI as EventsV1API, ListEventsOptionalParams,
Expand Down Expand Up @@ -65,16 +65,11 @@ pub async fn search(
to: String,
limit: i32,
) -> Result<()> {
// Events search is OAuth-excluded — require API keys
if !cfg.has_api_keys() {
bail!(
"events search requires API key authentication (DD_API_KEY + DD_APP_KEY).\n\
This endpoint does not support bearer token auth."
);
}

let dd_cfg = client::make_dd_config(cfg);
let api = EventsV2API::with_config(dd_cfg);
let api = match client::make_bearer_client(cfg) {
Some(c) => EventsV2API::with_client_and_config(dd_cfg, c),
None => EventsV2API::with_config(dd_cfg),
};

let from_ms = util::parse_time_to_unix_millis(&from)?;
let to_ms = util::parse_time_to_unix_millis(&to)?;
Expand Down
Loading