1use crate::client::ManagementClient;
15use crate::response::get_content_text;
16use anyhow::{anyhow, Context as _, Result};
17use derive_builder::Builder;
18use reqwest::header::{ACCEPT, AUTHORIZATION};
19use serde::{Deserialize, Serialize};
20use serde_aux::field_attributes::{deserialize_bool_from_anything, deserialize_default_from_null};
21
22#[derive(Debug, Deserialize)]
23#[serde(rename_all = "PascalCase")]
24struct CreateAccountResult {
25 pub account: Account,
26}
27
28#[derive(Debug, Deserialize)]
29#[serde(rename_all = "PascalCase")]
30struct ResponseMetadata {
31 pub request_id: String,
32}
33
34#[derive(Debug, Deserialize)]
35#[serde(rename_all = "PascalCase")]
36struct CreateAccountResponse {
37 pub response_metadata: ResponseMetadata,
38 pub create_account_result: CreateAccountResult,
39}
40
41#[derive(Debug, Deserialize)]
42#[serde(rename_all = "PascalCase")]
43struct TagAccountResponse {
44 pub response_metadata: ResponseMetadata,
45}
46
47#[derive(Debug, Deserialize)]
48#[serde(rename_all = "PascalCase")]
49struct GetAccountResult {
50 pub account: Account,
51}
52
53#[derive(Debug, Deserialize)]
54#[serde(rename_all = "PascalCase")]
55struct GetAccountResponse {
56 pub response_metadata: ResponseMetadata,
57 pub get_account_result: GetAccountResult,
58}
59
60#[derive(Debug, Deserialize)]
61#[serde(rename_all = "PascalCase")]
62struct UpdateAccountResult {
63 pub account: Account,
64}
65
66#[derive(Debug, Deserialize)]
67#[serde(rename_all = "PascalCase")]
68struct UpdateAccountResponse {
69 pub response_metadata: ResponseMetadata,
70 pub update_account_result: UpdateAccountResult,
71}
72
73#[derive(Debug, Deserialize)]
74#[serde(rename_all = "PascalCase")]
75struct DeleteAccountResponse {
76 pub response_metadata: ResponseMetadata,
77}
78
79#[derive(Debug, Deserialize)]
80#[serde(rename_all = "PascalCase")]
81struct DisableAccountResponse {
82 pub response_metadata: ResponseMetadata,
83}
84
85#[derive(Debug, Deserialize)]
86#[serde(rename_all = "PascalCase")]
87struct ListAccountsResult {
88 pub account_metadata: Vec<Account>,
89 pub is_truncated: bool,
90 pub marker: Option<String>,
91}
92
93#[derive(Debug, Deserialize)]
94#[serde(rename_all = "PascalCase")]
95struct ListAccountsResponse {
96 pub response_metadata: ResponseMetadata,
98 pub list_accounts_result: ListAccountsResult,
99}
100
101#[derive(Clone, Debug, Deserialize, Serialize)]
103#[serde(rename_all = "PascalCase")]
104pub struct Tag {
105 pub key: String,
107 pub value: String,
109}
110
111#[derive(Builder, Clone, Debug, Default, Deserialize, Serialize)]
131#[serde(rename_all = "PascalCase")]
132#[builder(setter(skip))]
133pub struct Account {
134 pub account_id: String,
136 pub objscale: String,
138 pub create_date: String,
140 #[builder(setter(skip = false), default = "false")]
142 #[serde(deserialize_with = "deserialize_bool_from_anything")]
143 pub encryption_enabled: bool,
144 #[serde(deserialize_with = "deserialize_bool_from_anything")]
146 pub account_disabled: bool,
147 #[builder(setter(into))]
148 pub alias: String,
150 #[builder(setter(into), default)]
151 #[serde(default)]
154 pub description: String,
155 #[serde(deserialize_with = "deserialize_bool_from_anything")]
157 pub protection_enabled: bool,
158 #[serde(default)]
161 pub tso_id: String,
162 #[builder(setter(skip = false), default)]
165 #[serde(default, deserialize_with = "deserialize_default_from_null")]
166 pub tags: Vec<Tag>,
167}
168
169impl Account {
170 pub(crate) fn create_account(
171 client: &mut ManagementClient,
172 account: Account,
173 ) -> Result<Account> {
174 let request_url = format!(
177 "{}iam?Action=CreateAccount&Alias={}&EncryptionEnabled={}&Description={}",
178 client.endpoint, account.alias, account.encryption_enabled, account.description,
179 );
180 let resp = client
181 .http_client
182 .post(request_url)
183 .header(ACCEPT, "application/json")
184 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
185 .send()?;
186 let text = get_content_text(resp)?;
187 let resp: CreateAccountResponse = serde_json::from_str(&text).with_context(|| {
188 format!(
189 "Unable to deserialise CreateAccountResponse. Body was: \"{}\"",
190 text
191 )
192 })?;
193 Ok(resp.create_account_result.account)
194 }
195
196 pub(crate) fn tag_account(
197 client: &mut ManagementClient,
198 account_id: &str,
199 tags: Vec<Tag>,
200 ) -> Result<()> {
201 if tags.is_empty() {
202 return Ok(());
203 }
204 let mut request_url = format!(
205 "{}iam?Action=TagAccount&AccountId={}",
206 client.endpoint, account_id,
207 );
208 for (index, tag) in tags.iter().enumerate() {
209 request_url = format!(
210 "{}&Tags.member.{}.Key={}&Tags.member.{}.Value={}",
211 request_url,
212 index + 1,
213 tag.key,
214 index + 1,
215 tag.value
216 );
217 }
218
219 let resp = client
220 .http_client
221 .post(request_url)
222 .header(ACCEPT, "application/json")
223 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
224 .send()?;
225 let text = get_content_text(resp)?;
226 let _: TagAccountResponse = serde_json::from_str(&text).with_context(|| {
227 format!(
228 "Unable to deserialise TagAccountResponse. Body was: \"{}\"",
229 text
230 )
231 })?;
232 Ok(())
233 }
234
235 pub(crate) fn get_account(client: &mut ManagementClient, account_id: &str) -> Result<Account> {
236 let request_url = format!(
237 "{}iam?Action=GetAccount&AccountId={}",
238 client.endpoint, account_id,
239 );
240 let resp = client
241 .http_client
242 .post(request_url)
243 .header(ACCEPT, "application/json")
244 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
245 .send()?;
246 let text = get_content_text(resp)?;
247 let resp: GetAccountResponse = serde_json::from_str(&text).with_context(|| {
248 format!(
249 "Unable to deserialise GetAccountResponse. Body was: \"{}\"",
250 text
251 )
252 })?;
253 Ok(resp.get_account_result.account)
254 }
255
256 pub(crate) fn update_account(
257 client: &mut ManagementClient,
258 account: Account,
259 ) -> Result<Account> {
260 let request_url = format!(
261 "{}iam?Action=UpdateAccount&AccountId={}&Alias={}&Description={}",
262 client.endpoint, account.account_id, account.alias, account.description,
263 );
264 let resp = client
265 .http_client
266 .post(request_url)
267 .header(ACCEPT, "application/json")
268 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
269 .send()?;
270 let text = get_content_text(resp)?;
271 let resp: UpdateAccountResponse = serde_json::from_str(&text).with_context(|| {
272 format!(
273 "Unable to deserialise UpdateAccountResponse. Body was: \"{}\"",
274 text
275 )
276 })?;
277 Ok(resp.update_account_result.account)
278 }
279
280 pub(crate) fn disable_account(client: &mut ManagementClient, account_id: &str) -> Result<()> {
281 let request_url = format!(
282 "{}iam?Action=DisableAccount&AccountId={}",
283 client.endpoint, account_id
284 );
285 let resp = client
286 .http_client
287 .post(request_url)
288 .header(ACCEPT, "application/json")
289 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
290 .send()?;
291 let text = get_content_text(resp)?;
292 let _: DisableAccountResponse = serde_json::from_str(&text).with_context(|| {
293 format!(
294 "Unable to deserialise DisableAccountResponse. Body was: \"{}\"",
295 text
296 )
297 })?;
298 Ok(())
299 }
300
301 pub(crate) fn delete_account(client: &mut ManagementClient, account_id: &str) -> Result<()> {
302 let request_url = format!(
303 "{}iam?Action=DeleteAccount&AccountId={}",
304 client.endpoint, account_id
305 );
306 let resp = client
307 .http_client
308 .post(request_url)
309 .header(ACCEPT, "application/json")
310 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
311 .send()?;
312 let text = get_content_text(resp)?;
313 let _: DeleteAccountResponse = serde_json::from_str(&text).with_context(|| {
314 format!(
315 "Unable to deserialise DeleteAccountResponse. Body was: \"{}\"",
316 text
317 )
318 })?;
319 Ok(())
320 }
321
322 pub(crate) fn list_accounts(client: &mut ManagementClient) -> Result<Vec<Account>> {
323 let request_url = format!("{}iam?Action=ListAccounts", client.endpoint);
324 let resp = client
325 .http_client
326 .post(request_url)
327 .header(ACCEPT, "application/json")
328 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
329 .send()?;
330 let text = get_content_text(resp)?;
331 let mut resp: ListAccountsResponse = serde_json::from_str(&text).with_context(|| {
332 format!(
333 "Unable to deserialise ListAccountsResponse. Body was: \"{}\"",
334 text
335 )
336 })?;
337 let mut accounts: Vec<Account> = vec![];
338 accounts.extend(resp.list_accounts_result.account_metadata);
339 while resp.list_accounts_result.is_truncated {
340 let request_url = format!(
341 "{}iam?Action=ListAccounts?Marker={}",
342 client.endpoint,
343 resp.list_accounts_result
344 .marker
345 .ok_or_else(|| anyhow!("No marker found"))?,
346 );
347 let response = client
348 .http_client
349 .post(request_url)
350 .header(ACCEPT, "application/json")
351 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
352 .send()?;
353 let text = get_content_text(response)?;
354 resp = serde_json::from_str(&text).with_context(|| {
355 format!(
356 "Unable to deserialise ListAccountsResponse. Body was: \"{}\"",
357 text
358 )
359 })?;
360 accounts.extend(resp.list_accounts_result.account_metadata);
361 }
362 Ok(accounts)
363 }
364}
365
366#[derive(Builder, Clone, Debug, Default, Deserialize, Serialize)]
370#[serde(rename_all = "PascalCase")]
371#[builder(setter(skip))]
372pub struct User {
373 pub arn: String,
375 #[serde(default)]
378 pub create_date: String,
379 pub path: String,
381 #[builder(setter(skip = false), default)]
384 #[serde(default)]
385 pub permissions_boundary: PermissionsBoundary,
386 pub user_id: String,
388 #[builder(setter(into))]
390 pub user_name: String,
391 #[builder(setter(skip = false), default)]
393 #[serde(default, deserialize_with = "deserialize_default_from_null")]
394 pub tags: Vec<Tag>,
395 #[builder(setter(into))]
396 #[serde(default)]
397 pub namespace: String,
398}
399
400#[derive(Clone, Debug, Default, Deserialize, Serialize)]
401#[serde(rename_all = "PascalCase")]
402pub struct PermissionsBoundary {
403 pub permissions_boundary_arn: String,
405 pub permissions_boundary_type: String,
407}
408
409#[derive(Debug, Deserialize)]
410#[serde(rename_all = "PascalCase")]
411struct CreateUserResult {
412 pub user: User,
413}
414
415#[derive(Debug, Deserialize)]
416#[serde(rename_all = "PascalCase")]
417struct CreateUserResponse {
418 pub response_metadata: ResponseMetadata,
419 pub create_user_result: CreateUserResult,
420}
421
422#[derive(Debug, Deserialize)]
423#[serde(rename_all = "PascalCase")]
424struct TagUserResponse {
425 pub response_metadata: ResponseMetadata,
426}
427
428#[derive(Debug, Deserialize)]
429#[serde(rename_all = "PascalCase")]
430struct GetUserResult {
431 pub user: User,
432}
433
434#[derive(Debug, Deserialize)]
435#[serde(rename_all = "PascalCase")]
436struct GetUserResponse {
437 pub response_metadata: ResponseMetadata,
438 pub get_user_result: GetUserResult,
439}
440
441#[derive(Debug, Deserialize)]
442#[serde(rename_all = "PascalCase")]
443struct DeleteUserResponse {
444 pub response_metadata: ResponseMetadata,
445}
446
447#[derive(Debug, Deserialize)]
448#[serde(rename_all = "PascalCase")]
449struct ListUsersResult {
450 pub users: Vec<User>,
451 pub is_truncated: bool,
452 pub marker: Option<String>,
453}
454
455#[derive(Debug, Deserialize)]
456#[serde(rename_all = "PascalCase")]
457struct ListUsersResponse {
458 pub response_metadata: ResponseMetadata,
459 pub list_users_result: ListUsersResult,
460}
461
462impl User {
463 pub(crate) fn create(client: &mut ManagementClient, user: User) -> Result<User> {
464 let request_url = format!(
465 "{}iam?Action=CreateUser&UserName={}",
466 client.endpoint, user.user_name,
467 );
468 let namespace = user.namespace;
469 let mut req = client
470 .http_client
471 .post(request_url)
472 .header(ACCEPT, "application/json")
473 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
474 .header("x-emc-namespace", &namespace);
475
476 if !user
477 .permissions_boundary
478 .permissions_boundary_arn
479 .is_empty()
480 {
481 req = req.query(&[(
482 "PermissionsBoundary",
483 user.permissions_boundary.permissions_boundary_arn,
484 )]);
485 }
486 for (index, tag) in user.tags.iter().enumerate() {
487 req = req.query(&[(&format!("Tags.member.{}.Key", index + 1), &tag.key)]);
488 req = req.query(&[(&format!("Tags.member.{}.Value", index + 1), &tag.value)]);
489 }
490
491 let resp = req.send()?;
492 let text = get_content_text(resp)?;
493 let resp: CreateUserResponse = serde_json::from_str(&text).with_context(|| {
494 format!(
495 "Unable to deserialise CreateUserResponse. Body was: \"{}\"",
496 text
497 )
498 })?;
499 let mut user = resp.create_user_result.user;
500 user.namespace = namespace;
501 Ok(user)
502 }
503
504 pub(crate) fn tag_user(
505 client: &mut ManagementClient,
506 user_name: &str,
507 namespace: &str,
508 tags: Vec<Tag>,
509 ) -> Result<()> {
510 if tags.is_empty() {
511 return Ok(());
512 }
513 let mut request_url = format!(
514 "{}iam?Action=TagUser&UserName={}",
515 client.endpoint, user_name,
516 );
517 for (index, tag) in tags.iter().enumerate() {
518 request_url = format!(
519 "{}&Tags.member.{}.Key={}&Tags.member.{}.Value={}",
520 request_url,
521 index + 1,
522 tag.key,
523 index + 1,
524 tag.value
525 );
526 }
527
528 let resp = client
529 .http_client
530 .post(request_url)
531 .header(ACCEPT, "application/json")
532 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
533 .header("x-emc-namespace", namespace)
534 .send()?;
535 let text = get_content_text(resp)?;
536 let _: TagUserResponse = serde_json::from_str(&text).with_context(|| {
537 format!(
538 "Unable to deserialise TagUserResponse. Body was: \"{}\"",
539 text
540 )
541 })?;
542 Ok(())
543 }
544
545 pub(crate) fn get(
546 client: &mut ManagementClient,
547 user_name: &str,
548 namespace: &str,
549 ) -> Result<User> {
550 let request_url = format!(
551 "{}iam?Action=GetUser&UserName={}",
552 client.endpoint, user_name,
553 );
554 let resp = client
555 .http_client
556 .post(request_url)
557 .header(ACCEPT, "application/json")
558 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
559 .header("x-emc-namespace", namespace)
560 .send()?;
561 let text = get_content_text(resp)?;
562 let resp: GetUserResponse = serde_json::from_str(&text).with_context(|| {
563 format!(
564 "Unable to deserialise GetUserResponse. Body was: \"{}\"",
565 text
566 )
567 })?;
568 let mut user = resp.get_user_result.user;
569 user.namespace = namespace.to_string();
570 Ok(user)
571 }
572
573 pub(crate) fn delete(
574 client: &mut ManagementClient,
575 user_name: &str,
576 namespace: &str,
577 ) -> Result<()> {
578 let request_url = format!(
579 "{}iam?Action=DeleteUser&UserName={}",
580 client.endpoint, user_name,
581 );
582 let resp = client
583 .http_client
584 .post(request_url)
585 .header(ACCEPT, "application/json")
586 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
587 .header("x-emc-namespace", namespace)
588 .send()?;
589 let text = get_content_text(resp)?;
590 let _: DeleteUserResponse = serde_json::from_str(&text).with_context(|| {
591 format!(
592 "Unable to deserialise DeleteUserResponse. Body was: \"{}\"",
593 text
594 )
595 })?;
596 Ok(())
597 }
598
599 pub(crate) fn list(client: &mut ManagementClient, namespace: &str) -> Result<Vec<User>> {
600 let request_url = format!("{}iam?Action=ListUsers", client.endpoint);
601 let resp = client
602 .http_client
603 .post(request_url)
604 .header(ACCEPT, "application/json")
605 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
606 .header("x-emc-namespace", namespace)
607 .send()?;
608 let text = get_content_text(resp)?;
609 let mut resp: ListUsersResponse = serde_json::from_str(&text).with_context(|| {
610 format!(
611 "Unable to deserialise ListUsersResponse. Body was: \"{}\"",
612 text
613 )
614 })?;
615 let mut users: Vec<User> = vec![];
616 users.extend(resp.list_users_result.users);
617 while resp.list_users_result.is_truncated {
618 let request_url = format!(
619 "{}iam?Action=ListUsers&Marker={}",
620 client.endpoint,
621 resp.list_users_result
622 .marker
623 .ok_or_else(|| anyhow!("No marker found"))?,
624 );
625 let response = client
626 .http_client
627 .post(request_url)
628 .header(ACCEPT, "application/json")
629 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
630 .header("x-emc-namespace", namespace)
631 .send()?;
632 let text = get_content_text(response)?;
633 resp = serde_json::from_str(&text).with_context(|| {
634 format!(
635 "Unable to deserialise ListUsersResponse. Body was: \"{}\"",
636 text
637 )
638 })?;
639 users.extend(resp.list_users_result.users);
640 }
641 users
642 .iter_mut()
643 .for_each(|user| user.namespace = namespace.to_string());
644 Ok(users)
645 }
646}
647
648#[derive(Builder, Clone, Debug, Default, Deserialize, Serialize)]
649#[serde(rename_all = "PascalCase")]
650#[builder(setter(skip))]
651pub struct UserPolicyAttachment {
652 #[builder(setter(into))]
653 #[serde(default)]
654 pub user_name: String,
655 pub policy_name: String,
656 #[builder(setter(into))]
657 pub policy_arn: String,
658 #[builder(setter(into))]
659 #[serde(default)]
660 pub namespace: String,
661}
662
663#[derive(Debug, Deserialize)]
664#[serde(rename_all = "PascalCase")]
665struct AttachUserPolicyResponse {
666 pub response_metadata: ResponseMetadata,
667}
668
669#[derive(Debug, Deserialize)]
670#[serde(rename_all = "PascalCase")]
671struct DetachUserPolicyResponse {
672 pub response_metadata: ResponseMetadata,
673}
674
675#[derive(Debug, Deserialize)]
676#[serde(rename_all = "PascalCase")]
677struct ListAttachedUserPoliciesResult {
678 pub attached_policies: Vec<UserPolicyAttachment>,
679 pub is_truncated: bool,
680 pub marker: Option<String>,
681}
682
683#[derive(Debug, Deserialize)]
684#[serde(rename_all = "PascalCase")]
685struct ListAttachedUserPoliciesResponse {
686 pub response_metadata: ResponseMetadata,
687 pub list_attached_user_policies_result: ListAttachedUserPoliciesResult,
688}
689
690impl UserPolicyAttachment {
691 pub(crate) fn create(
692 client: &mut ManagementClient,
693 user_policy_attachment: UserPolicyAttachment,
694 ) -> Result<UserPolicyAttachment> {
695 let request_url = format!(
696 "{}iam?Action=AttachUserPolicy&UserName={}&PolicyArn={}",
697 client.endpoint, user_policy_attachment.user_name, user_policy_attachment.policy_arn,
698 );
699
700 let resp = client
701 .http_client
702 .post(request_url)
703 .header(ACCEPT, "application/json")
704 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
705 .header("x-emc-namespace", &user_policy_attachment.namespace)
706 .send()?;
707 let text = get_content_text(resp)?;
708 let _: AttachUserPolicyResponse = serde_json::from_str(&text).with_context(|| {
709 format!(
710 "Unable to deserialise AttachUserPolicyResponse. Body was: \"{}\"",
711 text
712 )
713 })?;
714 Ok(user_policy_attachment)
715 }
716
717 pub(crate) fn delete(
718 client: &mut ManagementClient,
719 user_policy_attachment: UserPolicyAttachment,
720 ) -> Result<()> {
721 let request_url = format!(
722 "{}iam?Action=DetachUserPolicy&UserName={}&PolicyArn={}",
723 client.endpoint, user_policy_attachment.user_name, user_policy_attachment.policy_arn,
724 );
725
726 let resp = client
727 .http_client
728 .post(request_url)
729 .header(ACCEPT, "application/json")
730 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
731 .header("x-emc-namespace", user_policy_attachment.namespace)
732 .send()?;
733 let text = get_content_text(resp)?;
734 let _: DetachUserPolicyResponse = serde_json::from_str(&text).with_context(|| {
735 format!(
736 "Unable to deserialise DetachUserPolicyResponse. Body was: \"{}\"",
737 text
738 )
739 })?;
740 Ok(())
741 }
742
743 pub(crate) fn list(
744 client: &mut ManagementClient,
745 user_name: &str,
746 namespace: &str,
747 ) -> Result<Vec<UserPolicyAttachment>> {
748 let request_url = format!(
749 "{}iam?Action=ListAttachedUserPolicies&UserName={}",
750 client.endpoint, user_name,
751 );
752 let resp = client
753 .http_client
754 .post(request_url)
755 .header(ACCEPT, "application/json")
756 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
757 .header("x-emc-namespace", namespace)
758 .send()?;
759 let text = get_content_text(resp)?;
760 let mut resp: ListAttachedUserPoliciesResponse =
761 serde_json::from_str(&text).with_context(|| {
762 format!(
763 "Unable to deserialise ListAttachedUserPoliciesResponse. Body was: \"{}\"",
764 text
765 )
766 })?;
767 let mut attachments: Vec<UserPolicyAttachment> = vec![];
768 attachments.extend(resp.list_attached_user_policies_result.attached_policies);
769 while resp.list_attached_user_policies_result.is_truncated {
770 let request_url = format!(
771 "{}iam?Action=ListAttachedUserPolicies&UserName={}&Marker={}",
772 client.endpoint,
773 user_name,
774 resp.list_attached_user_policies_result
775 .marker
776 .ok_or_else(|| anyhow!("No marker found"))?,
777 );
778 let response = client
779 .http_client
780 .post(request_url)
781 .header(ACCEPT, "application/json")
782 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
783 .header("x-emc-namespace", namespace)
784 .send()?;
785 let text = get_content_text(response)?;
786 resp = serde_json::from_str(&text).with_context(|| {
787 format!(
788 "Unable to deserialise ListAttachedUserPoliciesResponse. Body was: \"{}\"",
789 text
790 )
791 })?;
792 attachments.extend(resp.list_attached_user_policies_result.attached_policies);
793 }
794 attachments.iter_mut().for_each(|attachment| {
795 attachment.namespace = namespace.to_string();
796 attachment.user_name = user_name.to_string();
797 });
798 Ok(attachments)
799 }
800}
801
802#[derive(Builder, Clone, Debug, Default, Deserialize, Serialize)]
803#[serde(rename_all = "PascalCase")]
804#[builder(setter(skip))]
805pub struct LoginProfile {
806 pub create_date: String,
807 #[builder(setter(into))]
808 pub user_name: String,
809 #[builder(setter(skip = false), default)]
810 #[serde(deserialize_with = "deserialize_default_from_null")]
811 pub password_reset_required: bool,
812 #[builder(setter(into))]
813 #[serde(default)]
814 pub password: String,
815 #[builder(setter(into))]
816 #[serde(default)]
817 pub namespace: String,
818}
819
820#[derive(Debug, Deserialize)]
821#[serde(rename_all = "PascalCase")]
822struct CreateLoginProfileResult {
823 pub login_profile: LoginProfile,
824}
825
826#[derive(Debug, Deserialize)]
827#[serde(rename_all = "PascalCase")]
828struct CreateLoginProfileResponse {
829 pub response_metadata: ResponseMetadata,
830 pub create_login_profile_result: CreateLoginProfileResult,
831}
832
833#[derive(Debug, Deserialize)]
834#[serde(rename_all = "PascalCase")]
835struct GetLoginProfileResult {
836 pub login_profile: LoginProfile,
837}
838
839#[derive(Debug, Deserialize)]
840#[serde(rename_all = "PascalCase")]
841struct GetLoginProfileResponse {
842 pub response_metadata: ResponseMetadata,
843 pub get_login_profile_result: GetLoginProfileResult,
844}
845
846#[derive(Debug, Deserialize)]
847#[serde(rename_all = "PascalCase")]
848struct DeleteLoginProfileResponse {
849 pub response_metadata: ResponseMetadata,
850}
851
852impl LoginProfile {
853 pub(crate) fn create(
854 client: &mut ManagementClient,
855 login_profile: LoginProfile,
856 ) -> Result<LoginProfile> {
857 let request_url = format!(
858 "{}iam?Action=CreateLoginProfile&UserName={}&Password={}&PasswordResetRequired={}",
859 client.endpoint,
860 login_profile.user_name,
861 login_profile.password,
862 login_profile.password_reset_required,
863 );
864
865 let namespace = login_profile.namespace;
866 let resp = client
867 .http_client
868 .post(request_url)
869 .header(ACCEPT, "application/json")
870 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
871 .header("x-emc-namespace", &namespace)
872 .send()?;
873 let text = get_content_text(resp)?;
874 let resp: CreateLoginProfileResponse = serde_json::from_str(&text).with_context(|| {
875 format!(
876 "Unable to deserialise CreateLoginProfileResponse. Body was: \"{}\"",
877 text
878 )
879 })?;
880 let mut login_profile = resp.create_login_profile_result.login_profile;
881 login_profile.namespace = namespace;
882 Ok(login_profile)
883 }
884
885 pub(crate) fn get(
886 client: &mut ManagementClient,
887 user_name: &str,
888 namespace: &str,
889 ) -> Result<LoginProfile> {
890 let request_url = format!(
891 "{}iam?Action=GetLoginProfile&UserName={}",
892 client.endpoint, user_name,
893 );
894
895 let resp = client
896 .http_client
897 .post(request_url)
898 .header(ACCEPT, "application/json")
899 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
900 .header("x-emc-namespace", namespace)
901 .send()?;
902 let text = get_content_text(resp)?;
903 let resp: GetLoginProfileResponse = serde_json::from_str(&text).with_context(|| {
904 format!(
905 "Unable to deserialise GetLoginProfileResponse. Body was: \"{}\"",
906 text
907 )
908 })?;
909 let mut login_profile = resp.get_login_profile_result.login_profile;
910 login_profile.namespace = namespace.to_string();
911 Ok(login_profile)
912 }
913
914 pub(crate) fn delete(
915 client: &mut ManagementClient,
916 user_name: &str,
917 namespace: &str,
918 ) -> Result<()> {
919 let request_url = format!(
920 "{}iam?Action=DeleteLoginProfile&UserName={}",
921 client.endpoint, user_name,
922 );
923
924 let resp = client
925 .http_client
926 .post(request_url)
927 .header(ACCEPT, "application/json")
928 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
929 .header("x-emc-namespace", namespace)
930 .send()?;
931 let text = get_content_text(resp)?;
932 let _: DeleteLoginProfileResponse = serde_json::from_str(&text).with_context(|| {
933 format!(
934 "Unable to deserialise DeleteLoginProfileResponse. Body was: \"{}\"",
935 text
936 )
937 })?;
938 Ok(())
939 }
940}
941
942#[derive(Builder, Clone, Debug, Default, Deserialize, Serialize)]
944#[serde(rename_all = "PascalCase")]
945#[builder(setter(skip))]
946pub struct AccessKey {
947 pub access_key_id: String,
949 pub create_date: String,
951 #[serde(default)]
953 pub secret_access_key: String,
954 pub status: String,
956 #[builder(setter(into))]
958 pub user_name: String,
959 #[builder(setter(into))]
960 #[serde(default)]
961 pub namespace: String,
962}
963
964#[derive(Debug, Deserialize)]
965#[serde(rename_all = "PascalCase")]
966struct CreateAccessKeyResult {
967 pub access_key: AccessKey,
968}
969
970#[derive(Debug, Deserialize)]
971#[serde(rename_all = "PascalCase")]
972struct CreateAccessKeyResponse {
973 pub response_metadata: ResponseMetadata,
974 pub create_access_key_result: CreateAccessKeyResult,
975}
976
977#[derive(Debug, Deserialize)]
978#[serde(rename_all = "PascalCase")]
979struct UpdateAccessKeyResponse {
980 pub response_metadata: ResponseMetadata,
981}
982
983#[derive(Debug, Deserialize)]
984#[serde(rename_all = "PascalCase")]
985struct DeleteAccessKeyResponse {
986 pub response_metadata: ResponseMetadata,
987}
988
989#[derive(Debug, Deserialize)]
990#[serde(rename_all = "PascalCase")]
991struct ListAccessKeysResult {
992 pub access_key_metadata: Vec<AccessKey>,
993 pub is_truncated: bool,
994 pub marker: Option<String>,
995}
996
997#[derive(Debug, Deserialize)]
998#[serde(rename_all = "PascalCase")]
999struct ListAccessKeysResponse {
1000 pub response_metadata: ResponseMetadata,
1001 pub list_access_keys_result: ListAccessKeysResult,
1002}
1003
1004impl AccessKey {
1005 pub(crate) fn create(
1006 client: &mut ManagementClient,
1007 access_key: AccessKey,
1008 ) -> Result<AccessKey> {
1009 let request_url = format!(
1010 "{}iam?Action=CreateAccessKey&UserName={}",
1011 client.endpoint, access_key.user_name,
1012 );
1013 let namespace = access_key.namespace;
1014 let resp = client
1015 .http_client
1016 .post(request_url)
1017 .header(ACCEPT, "application/json")
1018 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1019 .header("x-emc-namespace", &namespace)
1020 .send()?;
1021 let text = get_content_text(resp)?;
1022 let resp: CreateAccessKeyResponse = serde_json::from_str(&text).with_context(|| {
1023 format!(
1024 "Unable to deserialise CreateAccessKeyResponse. Body was: \"{}\"",
1025 text
1026 )
1027 })?;
1028 let mut access_key = resp.create_access_key_result.access_key;
1029 access_key.namespace = namespace;
1030 Ok(access_key)
1031 }
1032
1033 pub(crate) fn update(client: &mut ManagementClient, access_key: AccessKey) -> Result<()> {
1034 let request_url = format!(
1035 "{}iam?Action=UpdateAccessKey&UserName={}&AccessKeyId={}&Status={}",
1036 client.endpoint, access_key.user_name, access_key.access_key_id, access_key.status
1037 );
1038 let namespace = access_key.namespace;
1039 let resp = client
1040 .http_client
1041 .post(request_url)
1042 .header(ACCEPT, "application/json")
1043 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1044 .header("x-emc-namespace", &namespace)
1045 .send()?;
1046 let text = get_content_text(resp)?;
1047 let _: UpdateAccessKeyResponse = serde_json::from_str(&text).with_context(|| {
1048 format!(
1049 "Unable to deserialise UpdateAccessKeyResponse. Body was: \"{}\"",
1050 text
1051 )
1052 })?;
1053 Ok(())
1054 }
1055
1056 pub(crate) fn delete(
1057 client: &mut ManagementClient,
1058 access_key_id: &str,
1059 user_name: &str,
1060 namespace: &str,
1061 ) -> Result<()> {
1062 let request_url = format!(
1063 "{}iam?Action=DeleteAccessKey&UserName={}&AccessKeyId={}",
1064 client.endpoint, user_name, access_key_id,
1065 );
1066 let resp = client
1067 .http_client
1068 .post(request_url)
1069 .header(ACCEPT, "application/json")
1070 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1071 .header("x-emc-namespace", namespace)
1072 .send()?;
1073 let text = get_content_text(resp)?;
1074 let _: DeleteAccessKeyResponse = serde_json::from_str(&text).with_context(|| {
1075 format!(
1076 "Unable to deserialise DeleteAccessKeyResponse. Body was: \"{}\"",
1077 text
1078 )
1079 })?;
1080 Ok(())
1081 }
1082
1083 pub(crate) fn list(
1084 client: &mut ManagementClient,
1085 user_name: &str,
1086 namespace: &str,
1087 ) -> Result<Vec<AccessKey>> {
1088 let request_url = format!(
1089 "{}iam?Action=ListAccessKeys&UserName={}",
1090 client.endpoint, user_name
1091 );
1092 let resp = client
1093 .http_client
1094 .post(request_url)
1095 .header(ACCEPT, "application/json")
1096 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1097 .header("x-emc-namespace", namespace)
1098 .send()?;
1099 let text = get_content_text(resp)?;
1100 let mut resp: ListAccessKeysResponse = serde_json::from_str(&text).with_context(|| {
1101 format!(
1102 "Unable to deserialise ListAccessKeysResponse. Body was: \"{}\"",
1103 text
1104 )
1105 })?;
1106 let mut access_keys: Vec<AccessKey> = vec![];
1107 access_keys.extend(resp.list_access_keys_result.access_key_metadata);
1108 while resp.list_access_keys_result.is_truncated {
1109 let request_url = format!(
1110 "{}iam?Action=ListAccessKeys&UserName={}&Marker={}",
1111 client.endpoint,
1112 user_name,
1113 resp.list_access_keys_result
1114 .marker
1115 .ok_or_else(|| anyhow!("No marker found"))?,
1116 );
1117 let response = client
1118 .http_client
1119 .post(request_url)
1120 .header(ACCEPT, "application/json")
1121 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1122 .header("x-emc-namespace", namespace)
1123 .send()?;
1124 let text = get_content_text(response)?;
1125 resp = serde_json::from_str(&text).with_context(|| {
1126 format!(
1127 "Unable to deserialise ListAccessKeysResponse. Body was: \"{}\"",
1128 text
1129 )
1130 })?;
1131 access_keys.extend(resp.list_access_keys_result.access_key_metadata);
1132 }
1133 access_keys
1134 .iter_mut()
1135 .for_each(|access_key| access_key.namespace = namespace.to_string());
1136 Ok(access_keys)
1137 }
1138}
1139
1140#[derive(Builder, Clone, Debug, Default, Deserialize, Serialize)]
1142#[serde(rename_all = "PascalCase")]
1143#[builder(setter(skip))]
1144pub struct AccountAccessKey {
1145 pub access_key_id: String,
1147 pub create_date: String,
1149 #[serde(default)]
1151 pub secret_access_key: String,
1152 pub status: String,
1154 #[builder(setter(into))]
1156 pub account_id: String,
1157}
1158
1159#[derive(Debug, Deserialize)]
1160#[serde(rename_all = "PascalCase")]
1161struct CreateAccountAccessKeyResult {
1162 pub access_key: AccountAccessKey,
1163}
1164
1165#[derive(Debug, Deserialize)]
1166#[serde(rename_all = "PascalCase")]
1167struct CreateAccountAccessKeyResponse {
1168 pub response_metadata: ResponseMetadata,
1169 pub create_account_access_key_result: CreateAccountAccessKeyResult,
1170}
1171
1172#[derive(Debug, Deserialize)]
1173#[serde(rename_all = "PascalCase")]
1174struct UpdateAccountAccessKeyResponse {
1175 pub response_metadata: ResponseMetadata,
1176}
1177
1178#[derive(Debug, Deserialize)]
1179#[serde(rename_all = "PascalCase")]
1180struct DeleteAccountAccessKeyResponse {
1181 pub response_metadata: ResponseMetadata,
1182}
1183
1184#[derive(Debug, Deserialize)]
1185#[serde(rename_all = "PascalCase")]
1186struct ListAccountAccessKeysResult {
1187 #[serde(deserialize_with = "deserialize_default_from_null")]
1188 pub access_key_metadata: Vec<AccountAccessKey>,
1189}
1190
1191#[derive(Debug, Deserialize)]
1192#[serde(rename_all = "PascalCase")]
1193struct ListAccountAccessKeysResponse {
1194 pub response_metadata: ResponseMetadata,
1195 pub list_account_access_keys_result: ListAccountAccessKeysResult,
1196}
1197
1198impl AccountAccessKey {
1199 pub(crate) fn create(
1200 client: &mut ManagementClient,
1201 account_access_key: AccountAccessKey,
1202 ) -> Result<AccountAccessKey> {
1203 let request_url = format!(
1204 "{}iam?Action=CreateAccountAccessKey&AccountId={}",
1205 client.endpoint, account_access_key.account_id,
1206 );
1207 let resp = client
1208 .http_client
1209 .post(request_url)
1210 .header(ACCEPT, "application/json")
1211 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1212 .send()?;
1213 let text = get_content_text(resp)?;
1214 let resp: CreateAccountAccessKeyResponse =
1215 serde_json::from_str(&text).with_context(|| {
1216 format!(
1217 "Unable to deserialise CreateAccountAccessKeyResponse. Body was: \"{}\"",
1218 text
1219 )
1220 })?;
1221 Ok(resp.create_account_access_key_result.access_key)
1222 }
1223
1224 pub(crate) fn update(
1225 client: &mut ManagementClient,
1226 account_access_key: AccountAccessKey,
1227 ) -> Result<()> {
1228 let request_url = format!(
1229 "{}iam?Action=UpdateAccountAccessKey&AccountId={}&AccessKeyId={}&Status={}",
1230 client.endpoint,
1231 account_access_key.account_id,
1232 account_access_key.access_key_id,
1233 account_access_key.status
1234 );
1235 let resp = client
1236 .http_client
1237 .post(request_url)
1238 .header(ACCEPT, "application/json")
1239 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1240 .send()?;
1241 let text = get_content_text(resp)?;
1242 let _: UpdateAccountAccessKeyResponse = serde_json::from_str(&text).with_context(|| {
1243 format!(
1244 "Unable to deserialise UpdateAccountAccessKeyResponse. Body was: \"{}\"",
1245 text
1246 )
1247 })?;
1248 Ok(())
1249 }
1250
1251 pub(crate) fn delete(
1252 client: &mut ManagementClient,
1253 access_key_id: &str,
1254 account_id: &str,
1255 ) -> Result<()> {
1256 let request_url = format!(
1257 "{}iam?Action=DeleteAccountAccessKey&AccessKeyId={}&AccountId={}",
1258 client.endpoint, access_key_id, account_id,
1259 );
1260 let resp = client
1261 .http_client
1262 .post(request_url)
1263 .header(ACCEPT, "application/json")
1264 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1265 .send()?;
1266 let text = get_content_text(resp)?;
1267 let _: DeleteAccountAccessKeyResponse = serde_json::from_str(&text).with_context(|| {
1268 format!(
1269 "Unable to deserialise DeleteAccountAccessKeyResponse. Body was: \"{}\"",
1270 text
1271 )
1272 })?;
1273 Ok(())
1274 }
1275
1276 pub(crate) fn list(
1277 client: &mut ManagementClient,
1278 account_id: &str,
1279 ) -> Result<Vec<AccountAccessKey>> {
1280 let request_url = format!(
1281 "{}iam?Action=ListAccountAccessKeys&AccountId={}",
1282 client.endpoint, account_id
1283 );
1284 let resp = client
1285 .http_client
1286 .post(request_url)
1287 .header(ACCEPT, "application/json")
1288 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1289 .send()?;
1290 let text = get_content_text(resp)?;
1291 let resp: ListAccountAccessKeysResponse =
1292 serde_json::from_str(&text).with_context(|| {
1293 format!(
1294 "Unable to deserialise ListAccountAccessKeysResponse. Body was: \"{}\"",
1295 text
1296 )
1297 })?;
1298
1299 Ok(resp.list_account_access_keys_result.access_key_metadata)
1300 }
1301}
1302
1303#[derive(Builder, Clone, Debug, Default, Deserialize, Serialize)]
1305#[serde(rename_all = "PascalCase")]
1306#[builder(setter(skip))]
1307pub struct Policy {
1308 pub arn: String,
1310 pub attachment_count: i64,
1312 pub create_date: String,
1314 pub default_version_id: String,
1316 #[builder(setter(into), default)]
1318 pub description: String,
1319 pub is_attachable: bool,
1321 pub path: String,
1323 pub permissions_boundary_usage_count: i64,
1325 pub policy_id: String,
1327 #[builder(setter(into))]
1329 pub policy_name: String,
1330 pub update_date: String,
1332 #[builder(setter(into))]
1333 #[serde(default)]
1334 pub policy_document: String,
1335 #[builder(setter(into))]
1336 #[serde(default)]
1337 pub namespace: String,
1338}
1339
1340#[derive(Debug, Deserialize)]
1341#[serde(rename_all = "PascalCase")]
1342struct CreatePolicyResult {
1343 pub policy: Policy,
1344}
1345
1346#[derive(Debug, Deserialize)]
1347#[serde(rename_all = "PascalCase")]
1348struct CreatePolicyResponse {
1349 pub response_metadata: ResponseMetadata,
1350 pub create_policy_result: CreatePolicyResult,
1351}
1352
1353#[derive(Debug, Deserialize)]
1354#[serde(rename_all = "PascalCase")]
1355struct GetPolicyResult {
1356 pub policy: Policy,
1357}
1358
1359#[derive(Debug, Deserialize)]
1360#[serde(rename_all = "PascalCase")]
1361struct GetPolicyResponse {
1362 pub response_metadata: ResponseMetadata,
1363 pub get_policy_result: GetPolicyResult,
1364}
1365
1366#[derive(Debug, Deserialize)]
1367#[serde(rename_all = "PascalCase")]
1368struct DeletePolicyResponse {
1369 pub response_metadata: ResponseMetadata,
1370}
1371
1372#[derive(Debug, Deserialize)]
1373#[serde(rename_all = "PascalCase")]
1374struct ListPoliciesResult {
1375 pub policies: Vec<Policy>,
1376 pub is_truncated: bool,
1377 pub marker: Option<String>,
1378}
1379
1380#[derive(Debug, Deserialize)]
1381#[serde(rename_all = "PascalCase")]
1382struct ListPoliciesResponse {
1383 pub response_metadata: ResponseMetadata,
1384 pub list_policies_result: ListPoliciesResult,
1385}
1386
1387impl Policy {
1388 pub(crate) fn create(client: &mut ManagementClient, policy: Policy) -> Result<Policy> {
1389 let request_url = format!(
1390 "{}iam?Action=CreatePolicy&PolicyName={}&PolicyDocument={}&Description={}",
1391 client.endpoint, policy.policy_name, policy.policy_document, policy.description,
1392 );
1393 let namespace = policy.namespace;
1394 let resp = client
1395 .http_client
1396 .post(request_url)
1397 .header(ACCEPT, "application/json")
1398 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1399 .header("x-emc-namespace", &namespace)
1400 .send()?;
1401 let text = get_content_text(resp)?;
1402 let resp: CreatePolicyResponse = serde_json::from_str(&text).with_context(|| {
1403 format!(
1404 "Unable to deserialise CreatePolicyResponse. Body was: \"{}\"",
1405 text
1406 )
1407 })?;
1408 let mut policy = resp.create_policy_result.policy;
1409 policy.namespace = namespace;
1410 Ok(policy)
1411 }
1412
1413 pub(crate) fn get(
1414 client: &mut ManagementClient,
1415 policy_arn: &str,
1416 namespace: &str,
1417 ) -> Result<Policy> {
1418 let request_url = format!(
1419 "{}iam?Action=GetPolicy&PolicyArn={}",
1420 client.endpoint, policy_arn,
1421 );
1422 let resp = client
1423 .http_client
1424 .post(request_url)
1425 .header(ACCEPT, "application/json")
1426 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1427 .header("x-emc-namespace", namespace)
1428 .send()?;
1429 let text = get_content_text(resp)?;
1430 let resp: GetPolicyResponse = serde_json::from_str(&text).with_context(|| {
1431 format!(
1432 "Unable to deserialise GetPolicyResponse. Body was: \"{}\"",
1433 text
1434 )
1435 })?;
1436 let mut policy = resp.get_policy_result.policy;
1437 policy.namespace = namespace.to_string();
1438 Ok(policy)
1439 }
1440
1441 pub(crate) fn delete(
1442 client: &mut ManagementClient,
1443 policy_arn: &str,
1444 namespace: &str,
1445 ) -> Result<()> {
1446 let request_url = format!(
1447 "{}iam?Action=DeletePolicy&PolicyArn={}",
1448 client.endpoint, policy_arn,
1449 );
1450 let resp = client
1451 .http_client
1452 .post(request_url)
1453 .header(ACCEPT, "application/json")
1454 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1455 .header("x-emc-namespace", namespace)
1456 .send()?;
1457 let text = get_content_text(resp)?;
1458 let _: DeletePolicyResponse = serde_json::from_str(&text).with_context(|| {
1459 format!(
1460 "Unable to deserialise DeletePolicyResponse. Body was: \"{}\"",
1461 text
1462 )
1463 })?;
1464 Ok(())
1465 }
1466
1467 pub(crate) fn list(client: &mut ManagementClient, namespace: &str) -> Result<Vec<Policy>> {
1468 let request_url = format!("{}iam?Action=ListPolicies", client.endpoint);
1469 let resp = client
1470 .http_client
1471 .post(request_url)
1472 .header(ACCEPT, "application/json")
1473 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1474 .header("x-emc-namespace", namespace)
1475 .send()?;
1476 let text = get_content_text(resp)?;
1477 let mut resp: ListPoliciesResponse = serde_json::from_str(&text).with_context(|| {
1478 format!(
1479 "Unable to deserialise ListPoliciesResponse. Body was: \"{}\"",
1480 text
1481 )
1482 })?;
1483 let mut policies: Vec<Policy> = vec![];
1484 policies.extend(resp.list_policies_result.policies);
1485 while resp.list_policies_result.is_truncated {
1486 let request_url = format!(
1487 "{}iam?Action=ListPolicies&Marker={}",
1488 client.endpoint,
1489 resp.list_policies_result
1490 .marker
1491 .ok_or_else(|| anyhow!("No marker found"))?,
1492 );
1493 let response = client
1494 .http_client
1495 .post(request_url)
1496 .header(ACCEPT, "application/json")
1497 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1498 .header("x-emc-namespace", namespace)
1499 .send()?;
1500 let text = get_content_text(response)?;
1501 resp = serde_json::from_str(&text).with_context(|| {
1502 format!(
1503 "Unable to deserialise ListPoliciesResponse. Body was: \"{}\"",
1504 text
1505 )
1506 })?;
1507 policies.extend(resp.list_policies_result.policies);
1508 }
1509 policies
1510 .iter_mut()
1511 .for_each(|policy| policy.namespace = namespace.to_string());
1512 Ok(policies)
1513 }
1514}
1515
1516#[derive(Builder, Clone, Debug, Default, Deserialize, Serialize)]
1518#[serde(rename_all = "PascalCase")]
1519#[builder(setter(skip))]
1520pub struct Group {
1521 pub arn: String,
1523 #[serde(default)]
1526 pub create_date: String,
1527 pub path: String,
1529 pub group_id: String,
1531 #[builder(setter(into))]
1533 pub group_name: String,
1534 #[builder(setter(into))]
1535 #[serde(default)]
1536 pub namespace: String,
1537}
1538#[derive(Debug, Deserialize)]
1539#[serde(rename_all = "PascalCase")]
1540struct CreateGroupResult {
1541 pub group: Group,
1542}
1543
1544#[derive(Debug, Deserialize)]
1545#[serde(rename_all = "PascalCase")]
1546struct CreateGroupResponse {
1547 pub response_metadata: ResponseMetadata,
1548 pub create_group_result: CreateGroupResult,
1549}
1550
1551#[derive(Debug, Deserialize)]
1552#[serde(rename_all = "PascalCase")]
1553struct GetGroupResult {
1554 pub group: Group,
1555 pub users: Vec<User>,
1556 pub is_truncated: bool,
1557 pub marker: Option<String>,
1558}
1559
1560#[derive(Debug, Deserialize)]
1561#[serde(rename_all = "PascalCase")]
1562struct GetGroupResponse {
1563 pub response_metadata: ResponseMetadata,
1564 pub get_group_result: GetGroupResult,
1565}
1566
1567#[derive(Debug, Deserialize)]
1568#[serde(rename_all = "PascalCase")]
1569struct DeleteGroupResponse {
1570 pub response_metadata: ResponseMetadata,
1571}
1572
1573#[derive(Debug, Deserialize)]
1574#[serde(rename_all = "PascalCase")]
1575struct ListGroupsResult {
1576 pub groups: Vec<Group>,
1577 pub is_truncated: bool,
1578 pub marker: Option<String>,
1579}
1580
1581#[derive(Debug, Deserialize)]
1582#[serde(rename_all = "PascalCase")]
1583struct ListGroupsResponse {
1584 pub response_metadata: ResponseMetadata,
1585 pub list_groups_result: ListGroupsResult,
1586}
1587
1588impl Group {
1589 pub(crate) fn create(client: &mut ManagementClient, group: Group) -> Result<Group> {
1590 let request_url = format!(
1591 "{}iam?Action=CreateGroup&GroupName={}",
1592 client.endpoint, group.group_name,
1593 );
1594 let namespace = group.namespace;
1595 let resp = client
1596 .http_client
1597 .post(request_url)
1598 .header(ACCEPT, "application/json")
1599 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1600 .header("x-emc-namespace", &namespace)
1601 .send()?;
1602 let text = get_content_text(resp)?;
1603 let resp: CreateGroupResponse = serde_json::from_str(&text).with_context(|| {
1604 format!(
1605 "Unable to deserialise CreateGroupResponse. Body was: \"{}\"",
1606 text
1607 )
1608 })?;
1609 let mut group = resp.create_group_result.group;
1610 group.namespace = namespace;
1611 Ok(group)
1612 }
1613
1614 pub(crate) fn get(
1615 client: &mut ManagementClient,
1616 group_name: &str,
1617 namespace: &str,
1618 ) -> Result<Group> {
1619 let request_url = format!(
1620 "{}iam?Action=GetGroup&GroupName={}",
1621 client.endpoint, group_name,
1622 );
1623 let resp = client
1624 .http_client
1625 .post(request_url)
1626 .header(ACCEPT, "application/json")
1627 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1628 .header("x-emc-namespace", namespace)
1629 .send()?;
1630 let text = get_content_text(resp)?;
1631 let resp: GetGroupResponse = serde_json::from_str(&text).with_context(|| {
1632 format!(
1633 "Unable to deserialise GetGroupResponse. Body was: \"{}\"",
1634 text
1635 )
1636 })?;
1637 let mut group = resp.get_group_result.group;
1638 group.namespace = namespace.to_string();
1639 Ok(group)
1640 }
1641
1642 pub(crate) fn delete(
1643 client: &mut ManagementClient,
1644 group_name: &str,
1645 namespace: &str,
1646 ) -> Result<()> {
1647 let request_url = format!(
1648 "{}iam?Action=DeleteGroup&GroupName={}",
1649 client.endpoint, group_name,
1650 );
1651 let resp = client
1652 .http_client
1653 .post(request_url)
1654 .header(ACCEPT, "application/json")
1655 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1656 .header("x-emc-namespace", namespace)
1657 .send()?;
1658 let text = get_content_text(resp)?;
1659 let _: DeleteGroupResponse = serde_json::from_str(&text).with_context(|| {
1660 format!(
1661 "Unable to deserialise DeleteGroupResponse. Body was: \"{}\"",
1662 text
1663 )
1664 })?;
1665 Ok(())
1666 }
1667
1668 pub(crate) fn list(client: &mut ManagementClient, namespace: &str) -> Result<Vec<Group>> {
1669 let request_url = format!("{}iam?Action=ListGroups", client.endpoint);
1670 let resp = client
1671 .http_client
1672 .post(request_url)
1673 .header(ACCEPT, "application/json")
1674 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1675 .header("x-emc-namespace", namespace)
1676 .send()?;
1677 let text = get_content_text(resp)?;
1678 let mut resp: ListGroupsResponse = serde_json::from_str(&text).with_context(|| {
1679 format!(
1680 "Unable to deserialise ListGroupsResponse. Body was: \"{}\"",
1681 text
1682 )
1683 })?;
1684 let mut groups: Vec<Group> = vec![];
1685 groups.extend(resp.list_groups_result.groups);
1686 while resp.list_groups_result.is_truncated {
1687 let request_url = format!(
1688 "{}iam?Action=ListGroups&Marker={}",
1689 client.endpoint,
1690 resp.list_groups_result
1691 .marker
1692 .ok_or_else(|| anyhow!("No marker found"))?,
1693 );
1694 let response = client
1695 .http_client
1696 .post(request_url)
1697 .header(ACCEPT, "application/json")
1698 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1699 .header("x-emc-namespace", namespace)
1700 .send()?;
1701 let text = get_content_text(response)?;
1702 resp = serde_json::from_str(&text).with_context(|| {
1703 format!(
1704 "Unable to deserialise ListGroupsResponse. Body was: \"{}\"",
1705 text
1706 )
1707 })?;
1708 groups.extend(resp.list_groups_result.groups);
1709 }
1710 groups
1711 .iter_mut()
1712 .for_each(|group| group.namespace = namespace.to_string());
1713 Ok(groups)
1714 }
1715}
1716
1717#[derive(Builder, Clone, Debug, Default, Deserialize, Serialize)]
1718#[serde(rename_all = "PascalCase")]
1719#[builder(setter(skip))]
1720pub struct GroupPolicyAttachment {
1721 #[builder(setter(into))]
1722 #[serde(default)]
1723 pub group_name: String,
1724 pub policy_name: String,
1725 #[builder(setter(into))]
1726 pub policy_arn: String,
1727 #[builder(setter(into))]
1728 #[serde(default)]
1729 pub namespace: String,
1730}
1731
1732#[derive(Debug, Deserialize)]
1733#[serde(rename_all = "PascalCase")]
1734struct AttachGroupPolicyResponse {
1735 pub response_metadata: ResponseMetadata,
1736}
1737
1738#[derive(Debug, Deserialize)]
1739#[serde(rename_all = "PascalCase")]
1740struct DetachGroupPolicyResponse {
1741 pub response_metadata: ResponseMetadata,
1742}
1743
1744#[derive(Debug, Deserialize)]
1745#[serde(rename_all = "PascalCase")]
1746struct ListAttachedGroupPoliciesResult {
1747 pub attached_policies: Vec<GroupPolicyAttachment>,
1748 pub is_truncated: bool,
1749 pub marker: Option<String>,
1750}
1751
1752#[derive(Debug, Deserialize)]
1753#[serde(rename_all = "PascalCase")]
1754struct ListAttachedGroupPoliciesResponse {
1755 pub response_metadata: ResponseMetadata,
1756 pub list_attached_group_policies_result: ListAttachedGroupPoliciesResult,
1757}
1758
1759impl GroupPolicyAttachment {
1760 pub(crate) fn create(
1761 client: &mut ManagementClient,
1762 group_policy_attachment: GroupPolicyAttachment,
1763 ) -> Result<GroupPolicyAttachment> {
1764 let request_url = format!(
1765 "{}iam?Action=AttachGroupPolicy&GroupName={}&PolicyArn={}",
1766 client.endpoint, group_policy_attachment.group_name, group_policy_attachment.policy_arn,
1767 );
1768
1769 let resp = client
1770 .http_client
1771 .post(request_url)
1772 .header(ACCEPT, "application/json")
1773 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1774 .header("x-emc-namespace", &group_policy_attachment.namespace)
1775 .send()?;
1776 let text = get_content_text(resp)?;
1777 let _: AttachGroupPolicyResponse = serde_json::from_str(&text).with_context(|| {
1778 format!(
1779 "Unable to deserialise AttachGroupPolicyResponse. Body was: \"{}\"",
1780 text
1781 )
1782 })?;
1783 Ok(group_policy_attachment)
1784 }
1785
1786 pub(crate) fn delete(
1787 client: &mut ManagementClient,
1788 group_policy_attachment: GroupPolicyAttachment,
1789 ) -> Result<()> {
1790 let request_url = format!(
1791 "{}iam?Action=DetachGroupPolicy&GroupName={}&PolicyArn={}",
1792 client.endpoint, group_policy_attachment.group_name, group_policy_attachment.policy_arn,
1793 );
1794
1795 let resp = client
1796 .http_client
1797 .post(request_url)
1798 .header(ACCEPT, "application/json")
1799 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1800 .header("x-emc-namespace", group_policy_attachment.namespace)
1801 .send()?;
1802 let text = get_content_text(resp)?;
1803 let _: DetachGroupPolicyResponse = serde_json::from_str(&text).with_context(|| {
1804 format!(
1805 "Unable to deserialise DetachGroupPolicyResponse. Body was: \"{}\"",
1806 text
1807 )
1808 })?;
1809 Ok(())
1810 }
1811
1812 pub(crate) fn list(
1813 client: &mut ManagementClient,
1814 group_name: &str,
1815 namespace: &str,
1816 ) -> Result<Vec<GroupPolicyAttachment>> {
1817 let request_url = format!(
1818 "{}iam?Action=ListAttachedGroupPolicies&GroupName={}",
1819 client.endpoint, group_name,
1820 );
1821 let resp = client
1822 .http_client
1823 .post(request_url)
1824 .header(ACCEPT, "application/json")
1825 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1826 .header("x-emc-namespace", namespace)
1827 .send()?;
1828 let text = get_content_text(resp)?;
1829 let mut resp: ListAttachedGroupPoliciesResponse = serde_json::from_str(&text)
1830 .with_context(|| {
1831 format!(
1832 "Unable to deserialise ListAttachedGroupPoliciesResponse. Body was: \"{}\"",
1833 text
1834 )
1835 })?;
1836 let mut attachments: Vec<GroupPolicyAttachment> = vec![];
1837 attachments.extend(resp.list_attached_group_policies_result.attached_policies);
1838 while resp.list_attached_group_policies_result.is_truncated {
1839 let request_url = format!(
1840 "{}iam?Action=ListAttachedGroupPolicies&GroupName={}&Marker={}",
1841 client.endpoint,
1842 group_name,
1843 resp.list_attached_group_policies_result
1844 .marker
1845 .ok_or_else(|| anyhow!("No marker found"))?,
1846 );
1847 let response = client
1848 .http_client
1849 .post(request_url)
1850 .header(ACCEPT, "application/json")
1851 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1852 .header("x-emc-namespace", namespace)
1853 .send()?;
1854 let text = get_content_text(response)?;
1855 resp = serde_json::from_str(&text).with_context(|| {
1856 format!(
1857 "Unable to deserialise ListAttachedGroupPolicies. Body was: \"{}\"",
1858 text
1859 )
1860 })?;
1861 attachments.extend(resp.list_attached_group_policies_result.attached_policies);
1862 }
1863 attachments.iter_mut().for_each(|attachment| {
1864 attachment.namespace = namespace.to_string();
1865 attachment.group_name = group_name.to_string();
1866 });
1867 Ok(attachments)
1868 }
1869}
1870
1871#[derive(Builder, Clone, Debug, Default, Deserialize, Serialize)]
1873#[serde(rename_all = "PascalCase")]
1874#[builder(setter(skip))]
1875pub struct Role {
1876 pub arn: String,
1878 #[builder(setter(into))]
1880 pub assume_role_policy_document: String,
1881 pub create_date: String,
1883 #[builder(setter(into), default)]
1885 pub description: String,
1886 #[builder(setter(skip = false), default)]
1888 pub max_session_duration: i32,
1889 pub path: String,
1891 pub role_id: String,
1893 #[builder(setter(into))]
1895 pub role_name: String,
1896 #[builder(setter(skip = false), default)]
1898 #[serde(default, deserialize_with = "deserialize_default_from_null")]
1899 pub tags: Vec<Tag>,
1900 #[builder(setter(skip = false), default)]
1903 #[serde(default)]
1904 pub permissions_boundary: PermissionsBoundary,
1905 #[builder(setter(into))]
1906 #[serde(default)]
1907 pub namespace: String,
1908}
1909#[derive(Debug, Deserialize)]
1910#[serde(rename_all = "PascalCase")]
1911struct CreateRoleResult {
1912 pub role: Role,
1913}
1914
1915#[derive(Debug, Deserialize)]
1916#[serde(rename_all = "PascalCase")]
1917struct CreateRoleResponse {
1918 pub response_metadata: ResponseMetadata,
1919 pub create_role_result: CreateRoleResult,
1920}
1921
1922#[derive(Debug, Deserialize)]
1923#[serde(rename_all = "PascalCase")]
1924struct GetRoleResult {
1925 pub role: Role,
1926}
1927
1928#[derive(Debug, Deserialize)]
1929#[serde(rename_all = "PascalCase")]
1930struct GetRoleResponse {
1931 pub response_metadata: ResponseMetadata,
1932 pub get_role_result: GetRoleResult,
1933}
1934
1935#[derive(Debug, Deserialize)]
1936#[serde(rename_all = "PascalCase")]
1937struct UpdateRoleResult {
1938 pub role: Role,
1939}
1940
1941#[derive(Debug, Deserialize)]
1942#[serde(rename_all = "PascalCase")]
1943struct UpdateRoleResponse {
1944 pub response_metadata: ResponseMetadata,
1945 pub update_role_result: UpdateRoleResult,
1946}
1947
1948#[derive(Debug, Deserialize)]
1949#[serde(rename_all = "PascalCase")]
1950struct DeleteRoleResponse {
1951 pub response_metadata: ResponseMetadata,
1952}
1953
1954#[derive(Debug, Deserialize)]
1955#[serde(rename_all = "PascalCase")]
1956struct ListRolesResult {
1957 pub roles: Vec<Role>,
1958 pub is_truncated: bool,
1959 pub marker: Option<String>,
1960}
1961
1962#[derive(Debug, Deserialize)]
1963#[serde(rename_all = "PascalCase")]
1964struct ListRolesResponse {
1965 pub response_metadata: ResponseMetadata,
1966 pub list_roles_result: ListRolesResult,
1967}
1968
1969impl Role {
1970 pub(crate) fn create(client: &mut ManagementClient, role: Role) -> Result<Role> {
1971 let request_url = format!(
1972 "{}iam?Action=CreateRole&RoleName={}&AssumeRolePolicyDocument={}",
1973 client.endpoint, role.role_name, role.assume_role_policy_document,
1974 );
1975 let namespace = role.namespace;
1976 let mut req = client
1977 .http_client
1978 .post(request_url)
1979 .header(ACCEPT, "application/json")
1980 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
1981 .header("x-emc-namespace", &namespace);
1982
1983 if !role.description.is_empty() {
1984 req = req.query(&[("Description", role.description)]);
1985 }
1986 if role.max_session_duration > 0 {
1987 req = req.query(&[("MaxSessionDuration", role.max_session_duration)]);
1988 }
1989 if !role
1990 .permissions_boundary
1991 .permissions_boundary_arn
1992 .is_empty()
1993 {
1994 req = req.query(&[(
1995 "PermissionsBoundary",
1996 role.permissions_boundary.permissions_boundary_arn,
1997 )]);
1998 }
1999 for (index, tag) in role.tags.iter().enumerate() {
2000 req = req.query(&[(&format!("Tags.member.{}.Key", index + 1), &tag.key)]);
2001 req = req.query(&[(&format!("Tags.member.{}.Value", index + 1), &tag.value)]);
2002 }
2003 let resp = req.send()?;
2004 let text = get_content_text(resp)?;
2005 let resp: CreateRoleResponse = serde_json::from_str(&text).with_context(|| {
2006 format!(
2007 "Unable to deserialise CreateRoleResponse. Body was: \"{}\"",
2008 text
2009 )
2010 })?;
2011 let mut role = resp.create_role_result.role;
2012 role.namespace = namespace;
2013 Ok(role)
2014 }
2015
2016 pub(crate) fn get(
2017 client: &mut ManagementClient,
2018 role_name: &str,
2019 namespace: &str,
2020 ) -> Result<Role> {
2021 let request_url = format!(
2022 "{}iam?Action=GetRole&RoleName={}",
2023 client.endpoint, role_name,
2024 );
2025 let resp = client
2026 .http_client
2027 .post(request_url)
2028 .header(ACCEPT, "application/json")
2029 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
2030 .header("x-emc-namespace", namespace)
2031 .send()?;
2032 let text = get_content_text(resp)?;
2033 let resp: GetRoleResponse = serde_json::from_str(&text).with_context(|| {
2034 format!(
2035 "Unable to deserialise GetRoleResponse. Body was: \"{}\"",
2036 text
2037 )
2038 })?;
2039 let mut role = resp.get_role_result.role;
2040 role.namespace = namespace.to_string();
2041 Ok(role)
2042 }
2043
2044 pub(crate) fn update(client: &mut ManagementClient, role: Role) -> Result<Role> {
2045 let request_url = format!(
2046 "{}iam?Action=UpdateRole&RoleName={}",
2047 client.endpoint, role.role_name,
2048 );
2049 let namespace = role.namespace;
2050 let mut req = client
2051 .http_client
2052 .post(request_url)
2053 .header(ACCEPT, "application/json")
2054 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
2055 .header("x-emc-namespace", &namespace);
2056
2057 if !role.description.is_empty() {
2058 req = req.query(&[("Description", role.description)]);
2059 }
2060 if role.max_session_duration > 0 {
2061 req = req.query(&[("MaxSessionDuration", role.max_session_duration)]);
2062 }
2063
2064 let resp = req.send()?;
2065 let text = get_content_text(resp)?;
2066 let resp: UpdateRoleResponse = serde_json::from_str(&text).with_context(|| {
2067 format!(
2068 "Unable to deserialise UpdateRoleResponse. Body was: \"{}\"",
2069 text
2070 )
2071 })?;
2072 let mut role = resp.update_role_result.role;
2073 role.namespace = namespace;
2074 Ok(role)
2075 }
2076
2077 pub(crate) fn delete(
2078 client: &mut ManagementClient,
2079 role_name: &str,
2080 namespace: &str,
2081 ) -> Result<()> {
2082 let request_url = format!(
2083 "{}iam?Action=DeleteRole&RoleName={}",
2084 client.endpoint, role_name,
2085 );
2086 let resp = client
2087 .http_client
2088 .post(request_url)
2089 .header(ACCEPT, "application/json")
2090 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
2091 .header("x-emc-namespace", namespace)
2092 .send()?;
2093 let text = get_content_text(resp)?;
2094 let _: DeleteRoleResponse = serde_json::from_str(&text).with_context(|| {
2095 format!(
2096 "Unable to deserialise DeleteRoleResponse. Body was: \"{}\"",
2097 text
2098 )
2099 })?;
2100 Ok(())
2101 }
2102
2103 pub(crate) fn list(client: &mut ManagementClient, namespace: &str) -> Result<Vec<Role>> {
2104 let request_url = format!("{}iam?Action=ListRoles", client.endpoint);
2105 let resp = client
2106 .http_client
2107 .post(request_url)
2108 .header(ACCEPT, "application/json")
2109 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
2110 .header("x-emc-namespace", namespace)
2111 .send()?;
2112 let text = get_content_text(resp)?;
2113 let mut resp: ListRolesResponse = serde_json::from_str(&text).with_context(|| {
2114 format!(
2115 "Unable to deserialise ListRolesResponse. Body was: \"{}\"",
2116 text
2117 )
2118 })?;
2119 let mut roles: Vec<Role> = vec![];
2120 roles.extend(resp.list_roles_result.roles);
2121 while resp.list_roles_result.is_truncated {
2122 let request_url = format!(
2123 "{}iam?Action=ListRoles&Marker={}",
2124 client.endpoint,
2125 resp.list_roles_result
2126 .marker
2127 .ok_or_else(|| anyhow!("No marker found"))?,
2128 );
2129 let response = client
2130 .http_client
2131 .post(request_url)
2132 .header(ACCEPT, "application/json")
2133 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
2134 .header("x-emc-namespace", namespace)
2135 .send()?;
2136 let text = get_content_text(response)?;
2137 resp = serde_json::from_str(&text).with_context(|| {
2138 format!(
2139 "Unable to deserialise ListRolesResponse. Body was: \"{}\"",
2140 text
2141 )
2142 })?;
2143 roles.extend(resp.list_roles_result.roles);
2144 }
2145 roles
2146 .iter_mut()
2147 .for_each(|role| role.namespace = namespace.to_string());
2148 Ok(roles)
2149 }
2150}
2151
2152#[derive(Builder, Clone, Debug, Default, Deserialize, Serialize)]
2153#[serde(rename_all = "PascalCase")]
2154#[builder(setter(skip))]
2155pub struct RolePolicyAttachment {
2156 #[builder(setter(into))]
2157 #[serde(default)]
2158 pub role_name: String,
2159 pub policy_name: String,
2160 #[builder(setter(into))]
2161 pub policy_arn: String,
2162 #[builder(setter(into))]
2163 #[serde(default)]
2164 pub namespace: String,
2165}
2166
2167#[derive(Debug, Deserialize)]
2168#[serde(rename_all = "PascalCase")]
2169struct AttachRolePolicyResponse {
2170 pub response_metadata: ResponseMetadata,
2171}
2172
2173#[derive(Debug, Deserialize)]
2174#[serde(rename_all = "PascalCase")]
2175struct DetachRolePolicyResponse {
2176 pub response_metadata: ResponseMetadata,
2177}
2178
2179#[derive(Debug, Deserialize)]
2180#[serde(rename_all = "PascalCase")]
2181struct ListAttachedRolePoliciesResult {
2182 pub attached_policies: Vec<RolePolicyAttachment>,
2183 pub is_truncated: bool,
2184 pub marker: Option<String>,
2185}
2186
2187#[derive(Debug, Deserialize)]
2188#[serde(rename_all = "PascalCase")]
2189struct ListAttachedRolePoliciesResponse {
2190 pub response_metadata: ResponseMetadata,
2191 pub list_attached_role_policies_result: ListAttachedRolePoliciesResult,
2192}
2193
2194impl RolePolicyAttachment {
2195 pub(crate) fn create(
2196 client: &mut ManagementClient,
2197 role_policy_attachment: RolePolicyAttachment,
2198 ) -> Result<RolePolicyAttachment> {
2199 let request_url = format!(
2200 "{}iam?Action=AttachRolePolicy&RoleName={}&PolicyArn={}",
2201 client.endpoint, role_policy_attachment.role_name, role_policy_attachment.policy_arn,
2202 );
2203
2204 let resp = client
2205 .http_client
2206 .post(request_url)
2207 .header(ACCEPT, "application/json")
2208 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
2209 .header("x-emc-namespace", &role_policy_attachment.namespace)
2210 .send()?;
2211 let text = get_content_text(resp)?;
2212 let _: AttachRolePolicyResponse = serde_json::from_str(&text).with_context(|| {
2213 format!(
2214 "Unable to deserialise AttachRolePolicyResponse. Body was: \"{}\"",
2215 text
2216 )
2217 })?;
2218 Ok(role_policy_attachment)
2219 }
2220
2221 pub(crate) fn delete(
2222 client: &mut ManagementClient,
2223 role_policy_attachment: RolePolicyAttachment,
2224 ) -> Result<()> {
2225 let request_url = format!(
2226 "{}iam?Action=DetachRolePolicy&RoleName={}&PolicyArn={}",
2227 client.endpoint, role_policy_attachment.role_name, role_policy_attachment.policy_arn,
2228 );
2229
2230 let resp = client
2231 .http_client
2232 .post(request_url)
2233 .header(ACCEPT, "application/json")
2234 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
2235 .header("x-emc-namespace", role_policy_attachment.namespace)
2236 .send()?;
2237 let text = get_content_text(resp)?;
2238 let _: DetachRolePolicyResponse = serde_json::from_str(&text).with_context(|| {
2239 format!(
2240 "Unable to deserialise DetachRolePolicyResponse. Body was: \"{}\"",
2241 text
2242 )
2243 })?;
2244 Ok(())
2245 }
2246
2247 pub(crate) fn list(
2248 client: &mut ManagementClient,
2249 role_name: &str,
2250 namespace: &str,
2251 ) -> Result<Vec<RolePolicyAttachment>> {
2252 let request_url = format!(
2253 "{}iam?Action=ListAttachedRolePolicies&RoleName={}",
2254 client.endpoint, role_name,
2255 );
2256 let resp = client
2257 .http_client
2258 .post(request_url)
2259 .header(ACCEPT, "application/json")
2260 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
2261 .header("x-emc-namespace", namespace)
2262 .send()?;
2263 let text = get_content_text(resp)?;
2264 let mut resp: ListAttachedRolePoliciesResponse =
2265 serde_json::from_str(&text).with_context(|| {
2266 format!(
2267 "Unable to deserialise ListAttachedRolePoliciesResponse. Body was: \"{}\"",
2268 text
2269 )
2270 })?;
2271 let mut attachments: Vec<RolePolicyAttachment> = vec![];
2272 attachments.extend(resp.list_attached_role_policies_result.attached_policies);
2273 while resp.list_attached_role_policies_result.is_truncated {
2274 let request_url = format!(
2275 "{}iam?Action=ListAttachedRolePolicies&RoleName={}&Marker={}",
2276 client.endpoint,
2277 role_name,
2278 resp.list_attached_role_policies_result
2279 .marker
2280 .ok_or_else(|| anyhow!("No marker found"))?,
2281 );
2282 let response = client
2283 .http_client
2284 .post(request_url)
2285 .header(ACCEPT, "application/json")
2286 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
2287 .header("x-emc-namespace", namespace)
2288 .send()?;
2289 let text = get_content_text(response)?;
2290 resp = serde_json::from_str(&text).with_context(|| {
2291 format!(
2292 "Unable to deserialise ListAttachedRolePolicies. Body was: \"{}\"",
2293 text
2294 )
2295 })?;
2296 attachments.extend(resp.list_attached_role_policies_result.attached_policies);
2297 }
2298 attachments.iter_mut().for_each(|attachment| {
2299 attachment.namespace = namespace.to_string();
2300 attachment.role_name = role_name.to_string();
2301 });
2302 Ok(attachments)
2303 }
2304}
2305
2306#[derive(Clone, Debug, Serialize)]
2307#[serde(rename_all = "PascalCase")]
2308pub struct EntitiesForPolicy {
2309 pub users: Vec<String>,
2310 pub groups: Vec<String>,
2311 pub roles: Vec<String>,
2312}
2313
2314#[derive(Debug, Deserialize)]
2315#[serde(rename_all = "PascalCase")]
2316struct PolicyUser {
2317 pub user_name: String,
2318 pub user_id: String,
2319}
2320
2321#[derive(Debug, Deserialize)]
2322#[serde(rename_all = "PascalCase")]
2323struct PolicyGroup {
2324 pub group_name: String,
2325 pub group_id: String,
2326}
2327
2328#[derive(Debug, Deserialize)]
2329#[serde(rename_all = "PascalCase")]
2330struct PolicyRole {
2331 pub role_name: String,
2332 pub role_id: String,
2333}
2334
2335#[derive(Debug, Deserialize)]
2336#[serde(rename_all = "PascalCase")]
2337struct ListEntitiesForPolicyResult {
2338 pub policy_users: Vec<PolicyUser>,
2339 pub policy_groups: Vec<PolicyGroup>,
2340 pub policy_roles: Vec<PolicyRole>,
2341 pub is_truncated: bool,
2342 pub marker: Option<String>,
2343}
2344
2345#[derive(Debug, Deserialize)]
2346#[serde(rename_all = "PascalCase")]
2347struct ListEntitiesForPolicyResponse {
2348 pub response_metadata: ResponseMetadata,
2349 pub list_entities_for_policy_result: ListEntitiesForPolicyResult,
2350}
2351
2352impl EntitiesForPolicy {
2353 pub(crate) fn get(
2354 client: &mut ManagementClient,
2355 policy_arn: &str,
2356 namespace: &str,
2357 entity_filter: &str,
2358 usage_filter: &str,
2359 ) -> Result<EntitiesForPolicy> {
2360 let mut request_url = format!(
2361 "{}iam?Action=ListEntitiesForPolicy&PolicyArn={}",
2362 client.endpoint, policy_arn,
2363 );
2364 if !entity_filter.is_empty() {
2365 request_url = format!("{}&EntityFilter={}", request_url, entity_filter);
2366 }
2367 if !usage_filter.is_empty() {
2368 request_url = format!("{}&PolicyUsageFilter={}", request_url, usage_filter);
2369 }
2370 let resp = client
2371 .http_client
2372 .post(request_url)
2373 .header(ACCEPT, "application/json")
2374 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
2375 .header("x-emc-namespace", namespace)
2376 .send()?;
2377 let text = get_content_text(resp)?;
2378 let mut resp: ListEntitiesForPolicyResponse =
2379 serde_json::from_str(&text).with_context(|| {
2380 format!(
2381 "Unable to deserialise ListEntitiesForPolicyResponse. Body was: \"{}\"",
2382 text
2383 )
2384 })?;
2385 let mut attachment = EntitiesForPolicy {
2386 users: vec![],
2387 groups: vec![],
2388 roles: vec![],
2389 };
2390 attachment.users.extend(
2391 resp.list_entities_for_policy_result
2392 .policy_users
2393 .into_iter()
2394 .map(|u| u.user_name)
2395 .collect::<Vec<String>>(),
2396 );
2397 attachment.groups.extend(
2398 resp.list_entities_for_policy_result
2399 .policy_groups
2400 .into_iter()
2401 .map(|u| u.group_name)
2402 .collect::<Vec<String>>(),
2403 );
2404 attachment.roles.extend(
2405 resp.list_entities_for_policy_result
2406 .policy_roles
2407 .into_iter()
2408 .map(|u| u.role_name)
2409 .collect::<Vec<String>>(),
2410 );
2411 while resp.list_entities_for_policy_result.is_truncated {
2412 let request_url = format!(
2413 "{}iam?Action=ListEntitiesForPolicy&PolicyArn={}&PolicyUsageFilter={}&Marker={}",
2414 client.endpoint,
2415 policy_arn,
2416 entity_filter,
2417 resp.list_entities_for_policy_result
2418 .marker
2419 .ok_or_else(|| anyhow!("No marker found"))?,
2420 );
2421 let response = client
2422 .http_client
2423 .post(request_url)
2424 .header(ACCEPT, "application/json")
2425 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
2426 .header("x-emc-namespace", namespace)
2427 .send()?;
2428 let text = get_content_text(response)?;
2429 resp = serde_json::from_str(&text).with_context(|| {
2430 format!(
2431 "Unable to deserialise ListEntitiesForPolicyResponse. Body was: \"{}\"",
2432 text
2433 )
2434 })?;
2435 attachment.users.extend(
2436 resp.list_entities_for_policy_result
2437 .policy_users
2438 .into_iter()
2439 .map(|u| u.user_name)
2440 .collect::<Vec<String>>(),
2441 );
2442 attachment.groups.extend(
2443 resp.list_entities_for_policy_result
2444 .policy_groups
2445 .into_iter()
2446 .map(|u| u.group_name)
2447 .collect::<Vec<String>>(),
2448 );
2449 attachment.roles.extend(
2450 resp.list_entities_for_policy_result
2451 .policy_roles
2452 .into_iter()
2453 .map(|u| u.role_name)
2454 .collect::<Vec<String>>(),
2455 );
2456 }
2457 Ok(attachment)
2458 }
2459}
2460
2461#[derive(Builder, Clone, Debug, Default, Deserialize, Serialize)]
2462#[serde(rename_all = "PascalCase")]
2463#[builder(setter(skip))]
2464pub struct UserGroupMembership {
2465 #[builder(setter(into))]
2466 pub user_name: String,
2467 #[builder(setter(into))]
2468 pub group_name: String,
2469 #[builder(setter(into))]
2470 pub namespace: String,
2471}
2472
2473#[derive(Debug, Deserialize)]
2474#[serde(rename_all = "PascalCase")]
2475struct AddUserToGroupResponse {
2476 pub response_metadata: ResponseMetadata,
2477}
2478
2479#[derive(Debug, Deserialize)]
2480#[serde(rename_all = "PascalCase")]
2481struct RemoveUserFromGroupResponse {
2482 pub response_metadata: ResponseMetadata,
2483}
2484
2485#[derive(Debug, Deserialize)]
2486#[serde(rename_all = "PascalCase")]
2487struct ListGroupsForUserResult {
2488 pub groups: Vec<Group>,
2489 pub is_truncated: bool,
2490 pub marker: Option<String>,
2491}
2492
2493#[derive(Debug, Deserialize)]
2494#[serde(rename_all = "PascalCase")]
2495struct ListGroupsForUserResponse {
2496 pub response_metadata: ResponseMetadata,
2497 pub list_groups_for_user_result: ListGroupsForUserResult,
2498}
2499
2500impl UserGroupMembership {
2501 pub(crate) fn create(
2502 client: &mut ManagementClient,
2503 user_group_membership: UserGroupMembership,
2504 ) -> Result<UserGroupMembership> {
2505 let request_url = format!(
2506 "{}iam?Action=AddUserToGroup&UserName={}&GroupName={}",
2507 client.endpoint, user_group_membership.user_name, user_group_membership.group_name,
2508 );
2509
2510 let resp = client
2511 .http_client
2512 .post(request_url)
2513 .header(ACCEPT, "application/json")
2514 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
2515 .header("x-emc-namespace", &user_group_membership.namespace)
2516 .send()?;
2517 let text = get_content_text(resp)?;
2518 let _: AddUserToGroupResponse = serde_json::from_str(&text).with_context(|| {
2519 format!(
2520 "Unable to deserialise AttachUserPolicyResponse. Body was: \"{}\"",
2521 text
2522 )
2523 })?;
2524 Ok(user_group_membership)
2525 }
2526
2527 pub(crate) fn delete(
2528 client: &mut ManagementClient,
2529 user_group_membership: UserGroupMembership,
2530 ) -> Result<()> {
2531 let request_url = format!(
2532 "{}iam?Action=RemoveUserFromGroup&UserName={}&GroupName={}",
2533 client.endpoint, user_group_membership.user_name, user_group_membership.group_name,
2534 );
2535
2536 let resp = client
2537 .http_client
2538 .post(request_url)
2539 .header(ACCEPT, "application/json")
2540 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
2541 .header("x-emc-namespace", user_group_membership.namespace)
2542 .send()?;
2543 let text = get_content_text(resp)?;
2544 let _: RemoveUserFromGroupResponse = serde_json::from_str(&text).with_context(|| {
2545 format!(
2546 "Unable to deserialise RemoveUserFromGroupResponse. Body was: \"{}\"",
2547 text
2548 )
2549 })?;
2550 Ok(())
2551 }
2552
2553 pub(crate) fn list_by_user(
2554 client: &mut ManagementClient,
2555 user_name: &str,
2556 namespace: &str,
2557 ) -> Result<Vec<UserGroupMembership>> {
2558 let request_url = format!(
2559 "{}iam?Action=ListGroupsForUser&UserName={}",
2560 client.endpoint, user_name,
2561 );
2562 let resp = client
2563 .http_client
2564 .post(request_url)
2565 .header(ACCEPT, "application/json")
2566 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
2567 .header("x-emc-namespace", namespace)
2568 .send()?;
2569 let text = get_content_text(resp)?;
2570 let mut resp: ListGroupsForUserResponse =
2571 serde_json::from_str(&text).with_context(|| {
2572 format!(
2573 "Unable to deserialise ListGroupsForUserResponse. Body was: \"{}\"",
2574 text
2575 )
2576 })?;
2577 let mut memberships: Vec<UserGroupMembership> = vec![];
2578 memberships.extend(
2579 resp.list_groups_for_user_result
2580 .groups
2581 .into_iter()
2582 .map(|u| UserGroupMembership {
2583 user_name: user_name.to_string(),
2584 group_name: u.group_name,
2585 namespace: namespace.to_string(),
2586 })
2587 .collect::<Vec<UserGroupMembership>>(),
2588 );
2589 while resp.list_groups_for_user_result.is_truncated {
2590 let request_url = format!(
2591 "{}iam?Action=ListGroupsForUser&UserName={}&Marker={}",
2592 client.endpoint,
2593 user_name,
2594 resp.list_groups_for_user_result
2595 .marker
2596 .ok_or_else(|| anyhow!("No marker found"))?,
2597 );
2598 let response = client
2599 .http_client
2600 .post(request_url)
2601 .header(ACCEPT, "application/json")
2602 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
2603 .header("x-emc-namespace", namespace)
2604 .send()?;
2605 let text = get_content_text(response)?;
2606 resp = serde_json::from_str(&text).with_context(|| {
2607 format!(
2608 "Unable to deserialise ListGroupsForUserResponse. Body was: \"{}\"",
2609 text
2610 )
2611 })?;
2612 memberships.extend(
2613 resp.list_groups_for_user_result
2614 .groups
2615 .into_iter()
2616 .map(|u| UserGroupMembership {
2617 user_name: user_name.to_string(),
2618 group_name: u.group_name,
2619 namespace: namespace.to_string(),
2620 })
2621 .collect::<Vec<UserGroupMembership>>(),
2622 );
2623 }
2624 Ok(memberships)
2625 }
2626
2627 pub(crate) fn list_by_group(
2628 client: &mut ManagementClient,
2629 group_name: &str,
2630 namespace: &str,
2631 ) -> Result<Vec<UserGroupMembership>> {
2632 let request_url = format!(
2633 "{}iam?Action=GetGroup&GroupName={}",
2634 client.endpoint, group_name,
2635 );
2636 let resp = client
2637 .http_client
2638 .post(request_url)
2639 .header(ACCEPT, "application/json")
2640 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
2641 .header("x-emc-namespace", namespace)
2642 .send()?;
2643 let text = get_content_text(resp)?;
2644 let mut resp: GetGroupResponse = serde_json::from_str(&text).with_context(|| {
2645 format!(
2646 "Unable to deserialise GetGroupResponse. Body was: \"{}\"",
2647 text
2648 )
2649 })?;
2650 let mut memberships: Vec<UserGroupMembership> = vec![];
2651 memberships.extend(
2652 resp.get_group_result
2653 .users
2654 .into_iter()
2655 .map(|u| UserGroupMembership {
2656 user_name: u.user_name,
2657 group_name: group_name.to_string(),
2658 namespace: namespace.to_string(),
2659 })
2660 .collect::<Vec<UserGroupMembership>>(),
2661 );
2662
2663 while resp.get_group_result.is_truncated {
2664 let request_url = format!(
2665 "{}iam?Action=GetGroup&GroupName={}&Marker={}",
2666 client.endpoint,
2667 group_name,
2668 resp.get_group_result
2669 .marker
2670 .ok_or_else(|| anyhow!("No marker found"))?,
2671 );
2672 let response = client
2673 .http_client
2674 .post(request_url)
2675 .header(ACCEPT, "application/json")
2676 .header(AUTHORIZATION, client.access_token.as_ref().unwrap())
2677 .header("x-emc-namespace", namespace)
2678 .send()?;
2679 let text = get_content_text(response)?;
2680 resp = serde_json::from_str(&text).with_context(|| {
2681 format!(
2682 "Unable to deserialise GetGroupResponse. Body was: \"{}\"",
2683 text
2684 )
2685 })?;
2686 memberships.extend(
2687 resp.get_group_result
2688 .users
2689 .into_iter()
2690 .map(|u| UserGroupMembership {
2691 user_name: u.user_name,
2692 group_name: group_name.to_string(),
2693 namespace: namespace.to_string(),
2694 })
2695 .collect::<Vec<UserGroupMembership>>(),
2696 );
2697 }
2698 Ok(memberships)
2699 }
2700}