1pub mod app;
92pub mod build;
93pub mod client;
94pub mod identity;
95pub mod pipeline;
96pub mod policy;
97pub mod sandbox;
98pub mod scan;
99pub mod workflow;
100
101use reqwest::Error as ReqwestError;
102use std::fmt;
103
104pub use app::{
106 Application, ApplicationQuery, ApplicationsResponse, CreateApplicationRequest,
107 UpdateApplicationRequest,
108};
109pub use build::{
110 Build, BuildApi, BuildError, BuildList, CreateBuildRequest, DeleteBuildRequest,
111 DeleteBuildResult, GetBuildInfoRequest, GetBuildListRequest, UpdateBuildRequest,
112};
113pub use client::VeracodeClient;
114pub use identity::{
115 ApiCredential, BusinessUnit, CreateApiCredentialRequest, CreateTeamRequest, CreateUserRequest,
116 IdentityApi, IdentityError, Role, Team, UpdateTeamRequest, UpdateUserRequest, User, UserQuery,
117 UserType,
118};
119pub use pipeline::{
120 CreateScanRequest, DevStage, Finding, FindingsSummary, PipelineApi, PipelineError, Scan,
121 ScanConfig, ScanResults, ScanStage, ScanStatus, SecurityStandards, Severity,
122};
123pub use policy::{
124 PolicyApi, PolicyComplianceResult, PolicyComplianceStatus, PolicyError, PolicyRule,
125 PolicyScanRequest, PolicyScanResult, PolicyThresholds, ScanType, SecurityPolicy,
126};
127pub use sandbox::{
128 ApiError, ApiErrorResponse, CreateSandboxRequest, Sandbox, SandboxApi, SandboxError,
129 SandboxListParams, SandboxScan, UpdateSandboxRequest,
130};
131pub use scan::{
132 BeginPreScanRequest, BeginScanRequest, PreScanMessage, PreScanResults, ScanApi, ScanError,
133 ScanInfo, ScanModule, UploadFileRequest, UploadLargeFileRequest, UploadProgress,
134 UploadProgressCallback, UploadedFile,
135};
136pub use workflow::{VeracodeWorkflow, WorkflowConfig, WorkflowError, WorkflowResultData};
137#[derive(Debug)]
142pub enum VeracodeError {
143 Http(ReqwestError),
145 Serialization(serde_json::Error),
147 Authentication(String),
149 InvalidResponse(String),
151 InvalidConfig(String),
153 NotFound(String),
155}
156
157impl VeracodeClient {
158 fn new_xml_client(config: VeracodeConfig) -> Result<Self, VeracodeError> {
164 let mut xml_config = config.clone();
165 xml_config.base_url = config.xml_base_url;
166 Self::new(xml_config)
167 }
168
169 pub fn applications_api(&self) -> &Self {
172 self
173 }
174
175 pub fn sandbox_api(&self) -> SandboxApi {
178 SandboxApi::new(self)
179 }
180
181 pub fn identity_api(&self) -> IdentityApi {
184 IdentityApi::new(self)
185 }
186
187 pub fn pipeline_api(&self) -> PipelineApi {
190 PipelineApi::new(self.clone())
191 }
192
193 pub fn pipeline_api_with_debug(&self, debug: bool) -> PipelineApi {
196 PipelineApi::new_with_debug(self.clone(), debug)
197 }
198
199 pub fn policy_api(&self) -> PolicyApi {
202 PolicyApi::new(self)
203 }
204
205 pub fn scan_api(&self) -> ScanApi {
208 let xml_client = Self::new_xml_client(self.config().clone()).unwrap();
210 ScanApi::new(xml_client)
211 }
212
213 pub fn build_api(&self) -> build::BuildApi {
216 let xml_client = Self::new_xml_client(self.config().clone()).unwrap();
218 build::BuildApi::new(xml_client)
219 }
220
221 pub fn workflow(&self) -> workflow::VeracodeWorkflow {
224 workflow::VeracodeWorkflow::new(self.clone())
225 }
226}
227
228impl fmt::Display for VeracodeError {
229 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
230 match self {
231 VeracodeError::Http(e) => write!(f, "HTTP error: {e}"),
232 VeracodeError::Serialization(e) => write!(f, "Serialization error: {e}"),
233 VeracodeError::Authentication(e) => write!(f, "Authentication error: {e}"),
234 VeracodeError::InvalidResponse(e) => write!(f, "Invalid response: {e}"),
235 VeracodeError::InvalidConfig(e) => write!(f, "Invalid configuration: {e}"),
236 VeracodeError::NotFound(e) => write!(f, "Item not found: {e}"),
237 }
238 }
239}
240
241impl std::error::Error for VeracodeError {}
242
243impl From<ReqwestError> for VeracodeError {
244 fn from(error: ReqwestError) -> Self {
245 VeracodeError::Http(error)
246 }
247}
248
249impl From<serde_json::Error> for VeracodeError {
250 fn from(error: serde_json::Error) -> Self {
251 VeracodeError::Serialization(error)
252 }
253}
254
255#[derive(Clone)]
257pub struct SecureVeracodeApiId(String);
258
259#[derive(Clone)]
261pub struct SecureVeracodeApiKey(String);
262
263impl SecureVeracodeApiId {
264 pub fn new(api_id: String) -> Self {
265 SecureVeracodeApiId(api_id)
266 }
267
268 pub fn as_str(&self) -> &str {
269 &self.0
270 }
271
272 pub fn into_string(self) -> String {
273 self.0
274 }
275}
276
277impl SecureVeracodeApiKey {
278 pub fn new(api_key: String) -> Self {
279 SecureVeracodeApiKey(api_key)
280 }
281
282 pub fn as_str(&self) -> &str {
283 &self.0
284 }
285
286 pub fn into_string(self) -> String {
287 self.0
288 }
289}
290
291impl std::fmt::Debug for SecureVeracodeApiId {
292 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
293 f.write_str("[REDACTED]")
294 }
295}
296
297impl std::fmt::Debug for SecureVeracodeApiKey {
298 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
299 f.write_str("[REDACTED]")
300 }
301}
302
303#[derive(Clone)]
310pub struct VeracodeConfig {
311 pub api_id: SecureVeracodeApiId,
313 pub api_key: SecureVeracodeApiKey,
315 pub base_url: String,
317 pub rest_base_url: String,
319 pub xml_base_url: String,
321 pub region: VeracodeRegion,
323 pub validate_certificates: bool,
325}
326
327impl std::fmt::Debug for VeracodeConfig {
329 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
330 f.debug_struct("VeracodeConfig")
331 .field("api_id", &self.api_id)
332 .field("api_key", &self.api_key)
333 .field("base_url", &self.base_url)
334 .field("rest_base_url", &self.rest_base_url)
335 .field("xml_base_url", &self.xml_base_url)
336 .field("region", &self.region)
337 .field("validate_certificates", &self.validate_certificates)
338 .finish()
339 }
340}
341
342#[derive(Debug, Clone, Copy, PartialEq)]
347pub enum VeracodeRegion {
348 Commercial,
350 European,
352 Federal,
354}
355
356impl VeracodeConfig {
357 pub fn new(api_id: String, api_key: String) -> Self {
373 Self {
374 api_id: SecureVeracodeApiId::new(api_id),
375 api_key: SecureVeracodeApiKey::new(api_key),
376 base_url: "https://api.veracode.com".to_string(),
377 rest_base_url: "https://api.veracode.com".to_string(),
378 xml_base_url: "https://analysiscenter.veracode.com".to_string(),
379 region: VeracodeRegion::Commercial,
380 validate_certificates: true, }
382 }
383
384 pub fn with_region(mut self, region: VeracodeRegion) -> Self {
397 let (rest_url, xml_url) = match region {
398 VeracodeRegion::Commercial => (
399 "https://api.veracode.com",
400 "https://analysiscenter.veracode.com",
401 ),
402 VeracodeRegion::European => (
403 "https://api.veracode.eu",
404 "https://analysiscenter.veracode.eu",
405 ),
406 VeracodeRegion::Federal => (
407 "https://api.veracode.us",
408 "https://analysiscenter.veracode.us",
409 ),
410 };
411
412 self.region = region;
413 self.rest_base_url = rest_url.to_string();
414 self.xml_base_url = xml_url.to_string();
415 self.base_url = self.rest_base_url.clone(); self
417 }
418
419 pub fn with_certificate_validation_disabled(mut self) -> Self {
428 self.validate_certificates = false;
429 self
430 }
431}
432
433#[cfg(test)]
434mod tests {
435 use super::*;
436
437 #[test]
438 fn test_config_creation() {
439 let config = VeracodeConfig::new("test_api_id".to_string(), "test_api_key".to_string());
440
441 assert_eq!(config.api_id.as_str(), "test_api_id");
442 assert_eq!(config.api_key.as_str(), "test_api_key");
443 assert_eq!(config.base_url, "https://api.veracode.com");
444 assert_eq!(config.rest_base_url, "https://api.veracode.com");
445 assert_eq!(config.xml_base_url, "https://analysiscenter.veracode.com");
446 assert_eq!(config.region, VeracodeRegion::Commercial);
447 assert!(config.validate_certificates); }
449
450 #[test]
451 fn test_european_region_config() {
452 let config = VeracodeConfig::new("test_api_id".to_string(), "test_api_key".to_string())
453 .with_region(VeracodeRegion::European);
454
455 assert_eq!(config.base_url, "https://api.veracode.eu");
456 assert_eq!(config.rest_base_url, "https://api.veracode.eu");
457 assert_eq!(config.xml_base_url, "https://analysiscenter.veracode.eu");
458 assert_eq!(config.region, VeracodeRegion::European);
459 }
460
461 #[test]
462 fn test_federal_region_config() {
463 let config = VeracodeConfig::new("test_api_id".to_string(), "test_api_key".to_string())
464 .with_region(VeracodeRegion::Federal);
465
466 assert_eq!(config.base_url, "https://api.veracode.us");
467 assert_eq!(config.rest_base_url, "https://api.veracode.us");
468 assert_eq!(config.xml_base_url, "https://analysiscenter.veracode.us");
469 assert_eq!(config.region, VeracodeRegion::Federal);
470 }
471
472 #[test]
473 fn test_certificate_validation_disabled() {
474 let config = VeracodeConfig::new("test_api_id".to_string(), "test_api_key".to_string())
475 .with_certificate_validation_disabled();
476
477 assert!(!config.validate_certificates);
478 }
479
480 #[test]
481 fn test_secure_api_id_debug_redaction() {
482 let api_id = SecureVeracodeApiId::new("test_api_id_123".to_string());
483 let debug_output = format!("{api_id:?}");
484 assert_eq!(debug_output, "[REDACTED]");
485 assert!(!debug_output.contains("test_api_id_123"));
486 }
487
488 #[test]
489 fn test_secure_api_key_debug_redaction() {
490 let api_key = SecureVeracodeApiKey::new("test_api_key_456".to_string());
491 let debug_output = format!("{api_key:?}");
492 assert_eq!(debug_output, "[REDACTED]");
493 assert!(!debug_output.contains("test_api_key_456"));
494 }
495
496 #[test]
497 fn test_veracode_config_debug_redaction() {
498 let config = VeracodeConfig::new(
499 "test_api_id_123".to_string(),
500 "test_api_key_456".to_string(),
501 );
502 let debug_output = format!("{config:?}");
503
504 assert!(debug_output.contains("VeracodeConfig"));
506 assert!(debug_output.contains("api_id"));
507 assert!(debug_output.contains("api_key"));
508 assert!(debug_output.contains("[REDACTED]"));
509
510 assert!(!debug_output.contains("test_api_id_123"));
512 assert!(!debug_output.contains("test_api_key_456"));
513 }
514
515 #[test]
516 fn test_secure_api_id_access_methods() {
517 let api_id = SecureVeracodeApiId::new("test_api_id_123".to_string());
518
519 assert_eq!(api_id.as_str(), "test_api_id_123");
521
522 let string_value = api_id.into_string();
524 assert_eq!(string_value, "test_api_id_123");
525 }
526
527 #[test]
528 fn test_secure_api_key_access_methods() {
529 let api_key = SecureVeracodeApiKey::new("test_api_key_456".to_string());
530
531 assert_eq!(api_key.as_str(), "test_api_key_456");
533
534 let string_value = api_key.into_string();
536 assert_eq!(string_value, "test_api_key_456");
537 }
538
539 #[test]
540 fn test_secure_api_credentials_clone() {
541 let api_id = SecureVeracodeApiId::new("test_api_id_123".to_string());
542 let api_key = SecureVeracodeApiKey::new("test_api_key_456".to_string());
543
544 let cloned_api_id = api_id.clone();
545 let cloned_api_key = api_key.clone();
546
547 assert_eq!(api_id.as_str(), cloned_api_id.as_str());
549 assert_eq!(api_key.as_str(), cloned_api_key.as_str());
550 }
551
552 #[test]
553 fn test_error_display() {
554 let error = VeracodeError::Authentication("Invalid API key".to_string());
555 assert_eq!(format!("{error}"), "Authentication error: Invalid API key");
556 }
557
558 #[test]
559 fn test_error_from_reqwest() {
560 fn _test_conversion(error: reqwest::Error) -> VeracodeError {
565 VeracodeError::from(error)
566 }
567
568 }
571}