Skip to main content

devops_armory/cloud/gcp/iam/
update.rs

1use std::{
2    collections::HashSet, 
3    time::Duration
4};
5use super::models::{
6    SetPolicy,
7    PolicyBindings,
8    GcpProjectIam
9};
10
11/// Get IAM GCP project etag
12/// Required for IAM policy modification
13async fn get_iam_gcp_project_etag(
14    token: String,
15    project: String
16) -> Result<String, std::io::Error> {
17
18    let client = awc::Client::default();
19    let mut request = client
20        .post(format!("https://cloudresourcemanager.googleapis.com/v3/projects/{project}:getIamPolicy"))
21        .bearer_auth(token)
22        .timeout(Duration::from_secs(30))
23        .send()
24        .await
25        .expect("Request: GET Project IAM E-Tag could not been sent");
26
27    let body: SetPolicy = request.json::<SetPolicy>().await.unwrap_or_default();
28
29    let e_tag = body.etag;
30
31    Ok(e_tag)
32
33}
34
35/// Get Policy bindings for existing users
36async fn get_iam_gcp_project_policy(
37    token: String,
38    project: String
39) -> Result<Vec<PolicyBindings>, std::io::Error> {
40
41    let client = awc::Client::default();
42    let mut request = client
43        .post(format!("https://cloudresourcemanager.googleapis.com/v3/projects/{project}:getIamPolicy"))
44        .bearer_auth(token)
45        .timeout(Duration::from_secs(30))
46        .send()
47        .await
48        .expect("Request: GET Project IAM List could not been sent");
49
50    let body: SetPolicy = request.json::<SetPolicy>().await.unwrap_or_default();
51
52    let policy_bindings_vec = body.bindings;
53
54    Ok(policy_bindings_vec)
55
56}
57
58/// Update IAM policy
59/// Add roles/members to existing set
60pub async fn update_iam_gcp_project_policy(
61    token: String,
62    project: String,
63    iam_role: String,
64    iam_members: Vec<String>
65) {
66
67    let etag = get_iam_gcp_project_etag(
68        token.clone(),
69        project.clone()
70    ).await.unwrap_or_default();
71
72    let current_policy = get_iam_gcp_project_policy(
73        token.clone(),
74        project.clone()
75    ).await.unwrap_or_default();
76
77    let mut new_policy: HashSet<PolicyBindings> = HashSet::from_iter(current_policy);
78    
79    let iam_data: PolicyBindings = PolicyBindings { 
80        role: iam_role, 
81        members: iam_members 
82    };
83
84    let modified_hashset = new_policy.insert(iam_data);
85
86    let modified_vec: Vec<PolicyBindings> = new_policy.into_iter().collect();
87    
88
89    let project_policy: GcpProjectIam = GcpProjectIam { 
90        policy: SetPolicy { 
91            bindings: modified_vec, 
92            etag: etag,
93            version: 3
94        } 
95    };
96
97    let client = awc::Client::default();
98    let request = client
99        .post(format!("https://cloudresourcemanager.googleapis.com/v3/projects/{project}:setIamPolicy"))
100        .bearer_auth(token)
101        .timeout(Duration::from_secs(30))
102        .send_json(&project_policy)
103        .await
104        .expect("Request: POST Project IAM List could not been sent");
105    
106    let mut req = request;
107    let req_status = req.status().as_u16();
108    let respone = req.body().await.unwrap_or_default();
109
110    match req_status {
111
112        200 => {
113            println!("Request has been successfull: Status: {:?}, {:?}", req_status, respone);
114        },
115        400 => {
116            println!("Bad Request. Check URL parameters or body: {:?}", respone);
117        },
118        403 => {
119            println!("You don't have access to perform such request: {:?}", respone);
120        }
121        404 => {
122            println!("Requested resource does not exists: {:?}", respone);
123        },
124        409 => {
125            println!("Requested resource already exists! {:?}", respone)
126        }
127        _ => {
128            println!("Request status mismatch. Check response: {:?}", respone);
129        }
130
131    }
132
133}
134