Skip to main content

vantage_aws/models/iam/
group.rs

1use serde::{Deserialize, Serialize};
2use vantage_table::table::Table;
3
4use crate::types::{Arn, AwsDateTime};
5use crate::{AwsAccount, eq};
6
7use super::attached_policy::{AttachedPolicy, attached_group_policies_table};
8
9/// One IAM group from `ListGroups`. Same shape comes back from
10/// `ListGroupsForUser`, which is why both factories below produce
11/// `Table<AwsAccount, Group>`.
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct Group {
14    #[serde(rename = "GroupName")]
15    pub group_name: String,
16    #[serde(rename = "GroupId", default)]
17    pub group_id: String,
18    #[serde(rename = "Arn", default)]
19    pub arn: String,
20    #[serde(rename = "Path", default)]
21    pub path: String,
22    #[serde(rename = "CreateDate", default)]
23    pub create_date: String,
24}
25
26/// `ListGroups` table — every IAM group in the account. Optional
27/// filter: `PathPrefix`.
28///
29/// Relation:
30///   - `attached_policies` → `ListAttachedGroupPolicies` for this group
31pub fn groups_table(aws: AwsAccount) -> Table<AwsAccount, Group> {
32    Table::new("query/Groups:iam/2010-05-08.ListGroups", aws)
33        .with_id_column("GroupName")
34        .with_column_of::<String>("GroupId")
35        .with_column_of::<Arn>("Arn")
36        .with_title_column_of::<String>("Path")
37        .with_title_column_of::<AwsDateTime>("CreateDate")
38        .with_many(
39            "attached_policies",
40            "GroupName",
41            attached_group_policies_table,
42        )
43}
44
45/// `ListGroupsForUser` table — IAM groups that a given user belongs
46/// to. Requires `eq("UserName", "...")` before listing. Used as the
47/// `groups` relation on `User`; rarely interesting standalone.
48pub(crate) fn groups_for_user_table(aws: AwsAccount) -> Table<AwsAccount, Group> {
49    Table::new("query/Groups:iam/2010-05-08.ListGroupsForUser", aws)
50        .with_id_column("GroupName")
51        .with_column_of::<String>("GroupId")
52        .with_column_of::<Arn>("Arn")
53        .with_column_of::<String>("Path")
54        .with_column_of::<AwsDateTime>("CreateDate")
55}
56
57impl Group {
58    /// Build a [`groups_table`] narrowed to the group named in `arn`.
59    ///
60    /// Accepts ARNs of the shape
61    /// `arn:aws:iam::<account>:group/<name>`. Returns `None` if `arn`
62    /// isn't an IAM-group ARN.
63    pub fn from_arn(arn: &str, aws: AwsAccount) -> Option<Table<AwsAccount, Group>> {
64        let name = arn.strip_prefix("arn:aws:iam::")?.split(":group/").nth(1)?;
65        if name.is_empty() {
66            return None;
67        }
68        let mut t = groups_table(aws);
69        t.add_condition(eq("GroupName", name.to_string()));
70        Some(t)
71    }
72
73    /// Attached managed policies for *this* group.
74    pub fn ref_attached_policies(&self, aws: AwsAccount) -> Table<AwsAccount, AttachedPolicy> {
75        let mut t = attached_group_policies_table(aws);
76        t.add_condition(eq("GroupName", self.group_name.clone()));
77        t
78    }
79}