1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
#![allow(clippy::expect_used)]
use veracode_platform::{
VeracodeClient, VeracodeConfig,
identity::{
CreateApiCredentialRequest, CreateTeamRequest, CreateUserRequest, IdentityError,
UpdateUserRequest, UserQuery, UserType,
},
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = VeracodeConfig::new(
&std::env::var("VERACODE_API_ID").expect("VERACODE_API_ID environment variable required"),
&std::env::var("VERACODE_API_KEY").expect("VERACODE_API_KEY environment variable required"),
);
let client = VeracodeClient::new(config)?;
let identity_api = client.identity_api();
let timestamp = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.expect("system time should be after unix epoch")
.as_secs();
println!("๐๏ธ Identity Management Lifecycle Example\n");
// Example 1: List all roles to understand available permissions
println!("๐ Listing all available roles...");
let available_roles = match identity_api.list_roles().await {
Ok(roles) => {
println!("โ
Found {} roles:", roles.len());
for (i, role) in roles.iter().take(5).enumerate() {
let i: usize = i;
println!(
" {}. {} ({})",
i.saturating_add(1),
role.role_name,
role.role_id
);
if let Some(desc) = &role.role_description {
println!(" Description: {desc}");
}
}
if roles.len() > 5 {
println!(" ... and {} more roles", roles.len().saturating_sub(5));
}
roles
}
Err(e) => {
eprintln!("โ Failed to list roles: {e}");
Vec::new()
}
};
// Example 2: List existing teams
println!("\n๐ Listing existing teams...");
match identity_api.list_teams().await {
Ok(teams) => {
println!("โ
Found {} teams:", teams.len());
for (i, team) in teams.iter().take(3).enumerate() {
let i: usize = i;
println!(
" {}. {} ({})",
i.saturating_add(1),
team.team_name,
team.team_id
);
if let Some(desc) = &team.team_description {
println!(" Description: {desc}");
}
}
if teams.len() > 3 {
println!(" ... and {} more teams", teams.len().saturating_sub(3));
}
}
Err(e) => {
eprintln!("โ Failed to list teams: {e}");
}
}
// Example 3: Create a new team
println!("\n๐ฆ Creating a new team...");
let team_name = format!("Test Team {timestamp}");
let team_request = CreateTeamRequest {
team_name: team_name.clone(),
team_description: Some("A test team created for demonstration purposes".to_string()),
business_unit_id: None,
user_ids: None,
};
let created_team = match identity_api.create_team(team_request).await {
Ok(team) => {
println!("โ
Created team: {} ({})", team.team_name, team.team_id);
Some(team)
}
Err(IdentityError::TeamAlreadyExists(_)) => {
println!("โ ๏ธ Team already exists, continuing with example...");
None
}
Err(IdentityError::PermissionDenied(msg)) => {
println!("โ ๏ธ Permission denied to create team: {msg}");
println!(" This is expected if your API credentials don't have admin permissions");
None
}
Err(e) => {
eprintln!("โ Failed to create team: {e}");
None
}
};
// Example 4: Create a new user
println!("\n๐ค Creating a new user...");
let user_email = format!("testuser{timestamp}@example.com");
let username = format!("testuser{timestamp}");
// Find the submitter role specifically (human-only role)
let user_role_ids = if !available_roles.is_empty() {
// Look specifically for submitter role by description (with debug info)
println!(
"๐ Searching for Submitter role in {} available roles...",
available_roles.len()
);
// First, let's specifically look for extsubmitter
if let Some(extsubmitter_role) = available_roles
.iter()
.find(|r| r.role_name == "extsubmitter")
{
println!(
"๐ Found extsubmitter role for test user: {} ({})",
extsubmitter_role.role_name,
extsubmitter_role
.role_description
.as_ref()
.unwrap_or(&"No description".to_string())
);
Some(vec![extsubmitter_role.role_id.clone()])
} else if let Some(submitter_role) = available_roles.iter().find(|r| {
r.role_description
.as_ref()
.is_some_and(|desc| desc.trim() == "Submitter")
}) {
println!(
"๐ Found submitter role for test user: {} ({})",
submitter_role.role_name,
submitter_role
.role_description
.as_ref()
.unwrap_or(&"No description".to_string())
);
Some(vec![submitter_role.role_id.clone()])
} else {
// Debug: show first few role descriptions to help troubleshoot
println!(
"โ ๏ธ Neither extsubmitter nor Submitter role found. First 25 role descriptions:"
);
for (i, role) in available_roles.iter().take(25).enumerate() {
let i: usize = i;
println!(
" {}. {} - Description: '{}'",
i.saturating_add(1),
role.role_name,
role.role_description
.as_ref()
.unwrap_or(&"None".to_string())
);
}
println!("โ ๏ธ Using default role assignment.");
None
}
} else {
None
};
let user_request = CreateUserRequest {
email_address: user_email.clone(),
first_name: "Test".to_string(),
last_name: "User".to_string(),
user_name: Some(username),
user_type: Some(UserType::Human),
send_email_invitation: Some(false), // Don't send real emails in demo
role_ids: user_role_ids.clone(), // Use submitter role specifically
team_ids: created_team.as_ref().map(|t| vec![t.team_id.clone()]),
permissions: None, // Will use default permissions for human users
};
let created_user = match identity_api.create_user(user_request).await {
Ok(user) => {
println!(
"โ
Created user: {} {} ({})",
user.first_name, user.last_name, user.user_id
);
println!(" Email: {}", user.email_address);
println!(" Username: {}", user.user_name);
Some(user)
}
Err(IdentityError::UserAlreadyExists(_)) => {
println!("โ ๏ธ User already exists, continuing with example...");
None
}
Err(IdentityError::PermissionDenied(msg)) => {
println!("โ ๏ธ Permission denied to create user: {msg}");
println!(" This is expected if your API credentials don't have admin permissions");
None
}
Err(e) => {
eprintln!("โ Failed to create user: {e}");
None
}
};
// Example 4b: Create a Security Lead user (can work without team assignment) - DISABLED
// println!("\n๐ค Creating a Security Lead user (ignore team restrictions)...");
// let admin_user_email = format!("SecurityLead{}@example.com", timestamp);
// let admin_username = format!("SecurityLead{}", timestamp);
//
// // Find the Security Lead role which has ignore_team_restrictions: true
// let admin_role_ids = if !available_roles.is_empty() {
// // Look specifically for the Security Lead role
// if let Some(securitylead_role) = available_roles.iter().find(|r|
// r.role_name == "extseclead" ||
// r.role_description.as_ref().map_or(false, |desc| desc.trim() == "Security Lead")
// ) {
// println!("๐ Found Security Lead role: {} ({})",
// securitylead_role.role_name,
// securitylead_role.role_description.as_ref().unwrap_or(&"No description".to_string()));
// println!(" This role has ignore_team_restrictions: {:?}", securitylead_role.ignore_team_restrictions);
//
// // Show all available roles that ignore team restrictions for reference
// let team_restriction_roles: Vec<_> = available_roles.iter()
// .filter(|r| r.ignore_team_restrictions == Some(true) && r.is_api != Some(true))
// .collect();
//
// if team_restriction_roles.len() > 1 {
// println!(" Other available roles that ignore team restrictions:");
// for other_role in team_restriction_roles.iter().filter(|r| r.role_name != securitylead_role.role_name) {
// println!(" - {} ({})", other_role.role_name,
// other_role.role_description.as_ref().unwrap_or(&"No description".to_string()));
// }
// }
//
// Some(vec![securitylead_role.role_id.clone()])
// } else {
// println!("โ ๏ธ Security Lead role not found. Using regular submitter role with team assignment.");
// user_role_ids.clone()
// }
// } else {
// None
// };
//
// let admin_user_request = CreateUserRequest {
// email_address: admin_user_email.clone(),
// first_name: "Security Lead".to_string(),
// last_name: "User".to_string(),
// user_name: Some(admin_username),
// user_type: Some(UserType::Human),
// send_email_invitation: Some(false),
// role_ids: admin_role_ids.clone(),
// team_ids: if admin_role_ids.is_some() && available_roles.iter().any(|r|
// r.ignore_team_restrictions == Some(true) && r.is_api != Some(true)
// ) {
// None // Users with ignore_team_restrictions roles can be created without team assignment
// } else {
// created_team.as_ref().map(|t| vec![t.team_id.clone()]) // Fallback to team assignment
// },
// permissions: None,
// };
// let created_admin_user = match identity_api.create_user(admin_user_request).await {
// Ok(user) => {
// println!("โ
Created Security Lead user: {} {} ({})",
// user.first_name, user.last_name, user.user_id);
// println!(" Email: {}", user.email_address);
// println!(" This user can work without team assignment due to ignore_team_restrictions");
// Some(user)
// }
// Err(IdentityError::PermissionDenied(msg)) => {
// println!("โ ๏ธ Permission denied to create Security Lead user: {}", msg);
// None
// }
// Err(e) => {
// eprintln!("โ Failed to create Security Lead user: {}", e);
// None
// }
// };
println!("โญ๏ธ Skipping Security Lead user creation...");
//let created_admin_user: Option<veracode_api::identity::User> = None;
// Example 5: Search for users
println!("\n๐ Searching for users...");
let query = UserQuery::new()
.with_user_type(UserType::Human)
.with_pagination(0, 10);
match identity_api.list_users(Some(query)).await {
Ok(users) => {
println!("โ
Found {} users (showing first 5):", users.len());
for (i, user) in users.iter().take(5).enumerate() {
let i: usize = i;
println!(
" {}. {} {} - {}",
i.saturating_add(1),
user.first_name,
user.last_name,
user.email_address
);
println!(
" Active: {:?}, Type: {:?}",
user.active, user.user_type
);
}
}
Err(e) => {
eprintln!("โ Failed to search users: {e}");
}
}
// Example 5.5: Search for teams
println!("\n๐ Searching for teams...");
match identity_api.list_teams().await {
Ok(teams) => {
println!("โ
Found {} teams (showing first 5):", teams.len());
for (i, team) in teams.iter().take(5).enumerate() {
let i: usize = i;
println!(
" {}. {} ({})",
i.saturating_add(1),
team.team_name,
team.team_id
);
if let Some(desc) = &team.team_description {
println!(" Description: {desc}");
}
if let Some(bu) = &team.business_unit {
println!(" Business Unit: {}", bu.bu_name);
}
}
}
Err(e) => {
eprintln!("โ Failed to search teams: {e}");
}
}
// Example 6: Find a specific user by email
if let Some(ref user) = created_user {
println!("\n๐ Finding user by email...");
match identity_api.find_user_by_email(&user.email_address).await {
Ok(Some(found_user)) => {
println!(
"โ
Found user: {} {} ({})",
found_user.first_name, found_user.last_name, found_user.user_id
);
}
Ok(None) => {
println!("โ ๏ธ User not found by email search");
}
Err(e) => {
eprintln!("โ Error searching for user: {e}");
}
}
}
// Example 7: Update user information
if let Some(ref user) = created_user {
println!("\nโ๏ธ Updating user information...");
// Get current user's roles or use default roles
let current_roles = user
.roles
.as_ref()
.map(|roles| roles.iter().map(|r| r.role_id.clone()).collect())
.unwrap_or_else(|| {
// Fallback to submitter role if user has no roles (by description)
available_roles
.iter()
.find(|r| {
r.role_description
.as_ref()
.is_some_and(|desc| desc == "Submitter")
})
.map(|r| vec![r.role_id.clone()])
.unwrap_or_default()
});
// Get current user's teams or use the created team
let current_teams = user
.teams
.as_ref()
.map(|teams| teams.iter().map(|t| t.team_id.clone()).collect())
.unwrap_or_else(|| {
// Use the team that was assigned during creation
created_team
.as_ref()
.map(|t| vec![t.team_id.clone()])
.unwrap_or_default()
});
let update_request = UpdateUserRequest {
email_address: user.email_address.clone(),
user_name: user.user_name.clone(),
first_name: Some("Updated".to_string()),
last_name: Some("TestUser".to_string()),
active: None,
role_ids: current_roles,
team_ids: current_teams,
};
match identity_api
.update_user(&user.user_id, update_request)
.await
{
Ok(updated_user) => {
println!(
"โ
Updated user: {} {} -> {} {}",
user.first_name,
user.last_name,
updated_user.first_name,
updated_user.last_name
);
}
Err(IdentityError::PermissionDenied(msg)) => {
println!("โ ๏ธ Permission denied to update user: {msg}");
}
Err(e) => {
eprintln!("โ Failed to update user: {e}");
}
}
}
// Example 8: Create API service account
println!("\n๐ Creating API service account...");
let service_email = format!("serviceaccount{timestamp}@example.com");
// Find API roles for the service account - specifically look for apisubmitanyscan and noteamrestrictionapi
let api_role_ids = if !available_roles.is_empty() {
let mut api_roles: Vec<String> = Vec::new();
// Find apisubmitanyscan role
if let Some(submit_role) = available_roles
.iter()
.find(|r| r.role_name.to_lowercase() == "apisubmitanyscan" && r.is_api == Some(true))
{
api_roles.push(submit_role.role_id.clone());
}
// Find noteamrestrictionapi role
if let Some(noteam_role) = available_roles.iter().find(|r| {
r.role_name.to_lowercase() == "noteamrestrictionapi" && r.is_api == Some(true)
}) {
api_roles.push(noteam_role.role_id.clone());
}
api_roles
} else {
vec![]
};
let service_username = format!("serviceaccount{timestamp}");
match identity_api
.create_api_service_account(
&service_email,
&service_username,
"API",
"Service",
api_role_ids,
created_team.as_ref().map(|t| vec![t.team_id.clone()]), // Assign to test team
)
.await
{
Ok(service_user) => {
println!(
"โ
Created API service account: {} ({})",
service_user.email_address, service_user.user_id
);
// Example 9: Create API credentials for the service account
println!("\n๐ Creating API credentials...");
let creds_request = CreateApiCredentialRequest {
user_id: Some(service_user.user_id.clone()),
expiration_ts: None,
};
match identity_api.create_api_credentials(creds_request).await {
Ok(credentials) => {
println!("โ
Created API credentials:");
println!(" API ID: {}", credentials.api_id);
if let Some(api_key) = &credentials.api_key {
println!(" API Key: {api_key}");
}
println!(" Active: {:?}", credentials.active);
// Clean up: Revoke the API credentials
println!("\n๐๏ธ Revoking API credentials...");
match identity_api
.revoke_api_credentials(&credentials.api_id)
.await
{
Ok(_) => {
println!("โ
Successfully revoked API credentials");
}
Err(e) => {
eprintln!("โ Failed to revoke credentials: {e}");
}
}
}
Err(IdentityError::PermissionDenied(msg)) => {
println!("โ ๏ธ Permission denied to create API credentials: {msg}");
}
Err(e) => {
eprintln!("โ Failed to create API credentials: {e}");
}
}
// Clean up: Delete the service account
println!("\n๐๏ธ Deleting API service account...");
match identity_api.delete_user(&service_user.user_id).await {
Ok(_) => {
println!("โ
Successfully deleted API service account");
}
Err(IdentityError::PermissionDenied(msg)) => {
println!("โ ๏ธ Permission denied to delete user: {msg}");
}
Err(e) => {
eprintln!("โ Failed to delete service account: {e}");
}
}
}
Err(IdentityError::PermissionDenied(msg)) => {
println!("โ ๏ธ Permission denied to create API service account: {msg}");
}
Err(e) => {
eprintln!("โ Failed to create API service account: {e}");
}
}
// Clean up: Delete the test user
if let Some(ref user) = created_user {
println!("\n๐๏ธ Deleting test user...");
match identity_api.delete_user(&user.user_id).await {
Ok(_) => {
println!("โ
Successfully deleted test user");
}
Err(IdentityError::PermissionDenied(msg)) => {
println!("โ ๏ธ Permission denied to delete user: {msg}");
}
Err(e) => {
eprintln!("โ Failed to delete test user: {e}");
}
}
}
// Clean up: Delete the Security Lead test user (DISABLED)
// if let Some(ref user) = created_admin_user {
// println!("\n๐๏ธ Deleting Security Lead test user...");
// match identity_api.delete_user(&user.user_id).await {
// Ok(_) => {
// println!("โ
Successfully deleted Security Lead test user");
// }
// Err(IdentityError::PermissionDenied(msg)) => {
// println!("โ ๏ธ Permission denied to delete user: {}", msg);
// }
// Err(e) => {
// eprintln!("โ Failed to delete Security Lead test user: {}", e);
// }
// }
// }
// Clean up: Delete the test team
if let Some(ref team) = created_team {
println!("\n๐๏ธ Deleting test team...");
match identity_api.delete_team(&team.team_id).await {
Ok(_) => {
println!("โ
Successfully deleted test team");
}
Err(IdentityError::PermissionDenied(msg)) => {
println!("โ ๏ธ Permission denied to delete team: {msg}");
}
Err(IdentityError::TeamNotFound) => {
println!("โ ๏ธ Team not found (may have been already deleted)");
}
Err(e) => {
eprintln!("โ Failed to delete test team: {e}");
}
}
}
// Final cleanup: Delete all teams that start with "Test Team "
println!("\n๐งน Final cleanup: Deleting all teams starting with 'Test Team '...");
match identity_api.list_teams().await {
Ok(teams) => {
let test_teams: Vec<_> = teams
.iter()
.filter(|team| team.team_name.starts_with("Test Team "))
.collect();
if test_teams.is_empty() {
println!("โ
No test teams found to clean up");
} else {
println!("๐ Found {} test teams to delete:", test_teams.len());
for team in &test_teams {
println!(" - {} ({})", team.team_name, team.team_id);
}
let mut deleted_count: usize = 0;
let mut failed_count: usize = 0;
for team in test_teams {
match identity_api.delete_team(&team.team_id).await {
Ok(_) => {
println!("โ
Deleted team: {}", team.team_name);
deleted_count = deleted_count.saturating_add(1);
}
Err(IdentityError::PermissionDenied(_)) => {
println!("โ ๏ธ Permission denied to delete team: {}", team.team_name);
failed_count = failed_count.saturating_add(1);
}
Err(IdentityError::TeamNotFound) => {
println!("โ ๏ธ Team not found (already deleted): {}", team.team_name);
}
Err(e) => {
eprintln!("โ Failed to delete team {}: {}", team.team_name, e);
failed_count = failed_count.saturating_add(1);
}
}
}
println!("๐ Cleanup summary: {deleted_count} deleted, {failed_count} failed");
}
}
Err(e) => {
eprintln!("โ Failed to list teams for cleanup: {e}");
}
}
println!("\nโ
Identity lifecycle example completed!");
println!("\nThis example demonstrated:");
println!(" โ Listing roles and teams");
println!(" โ Creating teams and users (with team assignment)");
println!(" โญ๏ธ Creating Security Lead users (DISABLED)");
println!(" โ Searching for users and teams");
println!(" โ Updating user information");
println!(" โ Creating API service accounts (with team assignment and proper roles)");
println!(" โ Managing API credentials (create and revoke for service user)");
println!(" โ Team restriction validation for all user types");
println!(" โ Cleaning up all resources (users, teams)");
println!(" โ Final cleanup of all test teams");
println!("\nNote: Some operations may fail with permission errors");
println!(" if your API credentials don't have administrator privileges.");
Ok(())
}