1use crate::{
8 AwsHttpClient, Result,
9 ops::sts::StsOps,
10 types::sts::{
11 AssumeRoleRequest, AssumeRoleResponse, GetCallerIdentityRequest, GetCallerIdentityResponse,
12 },
13};
14
15pub struct StsClient<'a> {
17 ops: StsOps<'a>,
18}
19
20impl<'a> StsClient<'a> {
21 pub(crate) fn new(client: &'a AwsHttpClient) -> Self {
23 Self {
24 ops: StsOps::new(client),
25 }
26 }
27
28 pub async fn get_caller_identity(&self) -> Result<GetCallerIdentityResponse> {
31 let body = GetCallerIdentityRequest::default();
32 self.ops.get_caller_identity(&body).await
33 }
34
35 pub async fn assume_role(&self, body: &AssumeRoleRequest) -> Result<AssumeRoleResponse> {
37 self.ops.assume_role(body).await
38 }
39}
40
41#[cfg(test)]
42mod tests {
43 use crate::AwsHttpClient;
44 use crate::mock_client::MockClient;
45 use crate::test_support::sts_mock_helpers::StsMockHelpers;
46
47 fn xml_envelope(action: &str, inner: &str) -> Vec<u8> {
48 format!("<{action}Response><{action}Result>{inner}</{action}Result></{action}Response>")
49 .into_bytes()
50 }
51
52 #[tokio::test]
53 async fn get_caller_identity_returns_parsed_response() {
54 let mut mock = MockClient::new();
55 mock.expect_get_caller_identity()
56 .returning_bytes(xml_envelope(
57 "GetCallerIdentity",
58 "<Account>265411104181</Account>\
59 <Arn>arn:aws:iam::265411104181:root</Arn>\
60 <UserId>265411104181</UserId>",
61 ));
62
63 let client = AwsHttpClient::from_mock(mock);
64 let response = client.sts().get_caller_identity().await.unwrap();
65
66 assert_eq!(response.account.as_deref(), Some("265411104181"));
67 assert_eq!(
68 response.arn.as_deref(),
69 Some("arn:aws:iam::265411104181:root")
70 );
71 assert_eq!(response.user_id.as_deref(), Some("265411104181"));
72 }
73
74 #[tokio::test]
75 async fn assume_role_returns_credentials() {
76 let mut mock = MockClient::new();
77 mock.expect_assume_role().returning_bytes(xml_envelope(
78 "AssumeRole",
79 "<Credentials>\
80 <AccessKeyId>ASIATESTACCESSKEY</AccessKeyId>\
81 <SecretAccessKey>testsecretkey123</SecretAccessKey>\
82 <SessionToken>testsessiontoken456</SessionToken>\
83 <Expiration>2024-01-15T12:00:00Z</Expiration>\
84 </Credentials>\
85 <AssumedRoleUser>\
86 <AssumedRoleId>AROATESTROLE:test-session</AssumedRoleId>\
87 <Arn>arn:aws:sts::123456789012:assumed-role/TestRole/test-session</Arn>\
88 </AssumedRoleUser>",
89 ));
90
91 let client = AwsHttpClient::from_mock(mock);
92 let body = crate::types::sts::AssumeRoleRequest {
93 role_arn: "arn:aws:iam::123456789012:role/TestRole".to_string(),
94 role_session_name: "test-session".to_string(),
95 ..Default::default()
96 };
97 let response = client.sts().assume_role(&body).await.unwrap();
98
99 let creds = response
100 .credentials
101 .as_ref()
102 .expect("credentials should be set");
103 assert_eq!(creds.access_key_id, "ASIATESTACCESSKEY");
104 assert_eq!(creds.secret_access_key, "testsecretkey123");
105 assert_eq!(creds.session_token, "testsessiontoken456");
106 assert_eq!(creds.expiration, "2024-01-15T12:00:00Z");
107
108 let assumed = response
109 .assumed_role_user
110 .as_ref()
111 .expect("assumed role user should be set");
112 assert_eq!(assumed.assumed_role_id, "AROATESTROLE:test-session");
113 assert_eq!(
114 assumed.arn,
115 "arn:aws:sts::123456789012:assumed-role/TestRole/test-session"
116 );
117 }
118}