Skip to main content

rustack_sts_http/
router.rs

1//! STS request router.
2//!
3//! STS uses the `awsQuery` protocol where requests are `POST /` with
4//! `Content-Type: application/x-www-form-urlencoded`. The operation is
5//! specified by the `Action=<OperationName>` form parameter.
6
7use rustack_sts_model::{error::StsError, operations::StsOperation};
8
9/// Resolve an STS operation from parsed form parameters.
10///
11/// Looks for the `Action` parameter in the form body and maps it to
12/// the corresponding [`StsOperation`] variant.
13pub fn resolve_operation(params: &[(String, String)]) -> Result<StsOperation, StsError> {
14    let action = params
15        .iter()
16        .find(|(k, _)| k == "Action")
17        .map(|(_, v)| v.as_str())
18        .ok_or_else(StsError::missing_action)?;
19
20    StsOperation::from_name(action).ok_or_else(|| StsError::unknown_operation(action))
21}
22
23#[cfg(test)]
24mod tests {
25    use rustack_sts_model::error::StsErrorCode;
26
27    use super::*;
28
29    fn params_with_action(action: &str) -> Vec<(String, String)> {
30        vec![("Action".to_owned(), action.to_owned())]
31    }
32
33    #[test]
34    fn test_should_resolve_get_caller_identity() {
35        let params = params_with_action("GetCallerIdentity");
36        let op = resolve_operation(&params).unwrap();
37        assert_eq!(op, StsOperation::GetCallerIdentity);
38    }
39
40    #[test]
41    fn test_should_resolve_assume_role() {
42        let params = params_with_action("AssumeRole");
43        let op = resolve_operation(&params).unwrap();
44        assert_eq!(op, StsOperation::AssumeRole);
45    }
46
47    #[test]
48    fn test_should_resolve_get_session_token() {
49        let params = params_with_action("GetSessionToken");
50        let op = resolve_operation(&params).unwrap();
51        assert_eq!(op, StsOperation::GetSessionToken);
52    }
53
54    #[test]
55    fn test_should_resolve_get_access_key_info() {
56        let params = params_with_action("GetAccessKeyInfo");
57        let op = resolve_operation(&params).unwrap();
58        assert_eq!(op, StsOperation::GetAccessKeyInfo);
59    }
60
61    #[test]
62    fn test_should_error_on_missing_action() {
63        let params: Vec<(String, String)> = vec![];
64        let err = resolve_operation(&params).unwrap_err();
65        assert_eq!(err.code, StsErrorCode::MissingAction);
66    }
67
68    #[test]
69    fn test_should_error_on_unknown_operation() {
70        let params = params_with_action("NonExistentOperation");
71        let err = resolve_operation(&params).unwrap_err();
72        assert_eq!(err.code, StsErrorCode::InvalidAction);
73        assert!(err.message.contains("NonExistentOperation"));
74    }
75
76    #[test]
77    fn test_should_find_action_among_other_params() {
78        let params = vec![
79            ("Version".to_owned(), "2011-06-15".to_owned()),
80            ("Action".to_owned(), "AssumeRole".to_owned()),
81            (
82                "RoleArn".to_owned(),
83                "arn:aws:iam::123456789012:role/MyRole".to_owned(),
84            ),
85        ];
86        let op = resolve_operation(&params).unwrap();
87        assert_eq!(op, StsOperation::AssumeRole);
88    }
89}