从 Google 存储桶 IAM 政策中删除用户(身份)不起作用

Posted

技术标签:

【中文标题】从 Google 存储桶 IAM 政策中删除用户(身份)不起作用【英文标题】:Deletion of users (identities) from Google bucket IAM Policy does not work 【发布时间】:2019-11-09 22:29:13 【问题描述】:

为了从谷歌云存储桶中删除身份,我使用 GCP 示例存储库中提供的示例:here。我想知道是否缺少某些东西,我拥有云帐户的正确根凭据以及项目所有权凭据。基本上,从Java 代码和使用gcp Web 控制台的gsutil 函数都不会执行删除操作。

以下是原始政策:

Policy  
bindings=     
  roles/storage.legacyBucketOwner=      [  
     projectOwner:csbauditor
  ],
  roles/storage.objectAdmin=      [  
     serviceAccount:company-kiehn-log@csbauditor.iam.gserviceaccount.com,
     serviceAccount:company-kiehn-file@csbauditor.iam.gserviceaccount.com,
     serviceAccount:company-howe-file@csbauditor.iam.gserviceaccount.com,
     serviceAccount:company-satterfield-log@csbauditor.iam.gserviceaccount.com,
     serviceAccount:customer-0c1e8536-8bf5-46f4-8e@csbauditor.iam.gserviceaccount.com,
     serviceAccount:company-fahey-log@csbauditor.iam.gserviceaccount.com,
     serviceAccount:company-hammes-file@csbauditor.iam.gserviceaccount.com,
     serviceAccount:company-howe-log@csbauditor.iam.gserviceaccount.com,
     serviceAccount:company-sipes-file@csbauditor.iam.gserviceaccount.com,
     serviceAccount:company-doyle-log@csbauditor.iam.gserviceaccount.com,
     serviceAccount:customer-6a53ee71-95eb-49b2-8a@csbauditor.iam.gserviceaccount.com,
     serviceAccount:company-bergnaum-file@csbauditor.iam.gserviceaccount.com
  ],
  roles/storage.legacyBucketReader=      [  
     projectViewer:csbauditor
  ],
  roles/storage.objectViewer=      [  
   serviceAccount:company-block-log@csbauditor.iam.gserviceaccount.com
  ]
 ,
   etag=CLgE,
      version=0
 

这是第二个政策版本,在写信给 IAM 之前:

 Policy  
 bindings=     
    roles/storage.legacyBucketOwner=      [  
      projectOwner:csbauditor
  ],
  roles/storage.objectAdmin=      [  
     serviceAccount:company-kiehn-log@csbauditor.iam.gserviceaccount.com,
     serviceAccount:company-kiehn-file@csbauditor.iam.gserviceaccount.com,
     serviceAccount:company-howe-file@csbauditor.iam.gserviceaccount.com,
     serviceAccount:company-satterfield-log@csbauditor.iam.gserviceaccount.com,
     serviceAccount:customer-0c1e8536-8bf5-46f4-8e@csbauditor.iam.gserviceaccount.com,
     serviceAccount:company-fahey-log@csbauditor.iam.gserviceaccount.com,
     serviceAccount:company-hammes-file@csbauditor.iam.gserviceaccount.com,
     serviceAccount:company-howe-log@csbauditor.iam.gserviceaccount.com,
     serviceAccount:company-sipes-file@csbauditor.iam.gserviceaccount.com,
     serviceAccount:company-doyle-log@csbauditor.iam.gserviceaccount.com,
     serviceAccount:customer-6a53ee71-95eb-49b2-8a@csbauditor.iam.gserviceaccount.com,
     serviceAccount:company-bergnaum-file@csbauditor.iam.gserviceaccount.com
  ],
  roles/storage.legacyBucketReader=      [  
     projectViewer:csbauditor
  ],
  roles/storage.objectViewer=      [  
     serviceAccount:company-block-log@csbauditor.iam.gserviceaccount.com
  ]
,
etag=CLgE,
version=0

这是我的代码 sn-p:

读取存储桶策略并提取不需要的身份

Set<Identity> wrongIdentities = new HashSet<Identity>();
Role roler = null;    
Policy p = Cache.GCSStorage.getIamPolicy("bucketxyz");
Map<Role, Set<Identity>> policyBindings = p.getBindings();
    for (Map.Entry<Role, Set<Identity>> entry : policyBindings.entrySet()) 
Set<Identity> setidentities = entry.getValue();
    roler = entry.getKey();

        if (roler.getValue().equals("roles/storage.objectAdmin")) 
           setidentities = entry.getValue();
            if ((set.equals("serviceAccount:attacker@csbauditor.iam.gserviceaccount.com"))) 
                    continue;
                 else 
                    wrongIdentities.add(set);
                    
                
        
    
  removeBucketIamMember("bucektxyz", roler, identity));
    
 

从政策中移除不需要的身份

public static Policy removeBucketIamMember(String bucketName, Role role, 
Identity identity) 
Storage storage = GoogleStorage.initStorage();
Policy policy = storage.getIamPolicy(bucketName);
System.out.println("policyt "+ policy);
Policy updatedPolicy = policy.toBuilder().removeIdentity(role, 
Identity.serviceAccount(identity.getValue())).build();
System.out.println("updatedPolicy "+ policy);
storage.setIamPolicy(bucketName,updatedPolicy);
if (updatedPolicy.getBindings().get(role) == null|| 
!updatedPolicy.getBindings().get(role).contains(identity))  
System.out.printf("Removed %s with role %s from %s\n", identity, role, 
bucketName);
 
return updatedPolicy;

更新 01 我也尝试在 Web 控制台中使用 gsutil,但仍然无法正常工作。

myaccount@cloudshell:~ (csbauditor)$ gsutil iam ch -d user:company-sipes- 
file@csbauditor.iam.gserviceaccount.com  gs://company-block-log-fce65e82-a0cd- 
4f71-8693-381100d93c18

No changes made to gs://company-block-log-fce65e82-a0cd-4f71-8693-381100d93c18/

更新 02 根据@JohnHanley 的建议,gsutil 在我将user 替换为serviceAccount 后工作。但是,java 代码还不能运行。

【问题讨论】:

将策略显示为已读,然后再将其写回格式化,以便我可以轻松阅读。将 JSON 放入格式化工具中。 @JohnHanley 我已经更新了这个问题,显示了政策的第一个版本和下一个版本。由于篇幅原因,仅包括这​​两个,但是除了不断变化的eTag 之外,没有任何变化。 对于您的gsutil 命令,将user: 更改为serviceAccount: 我仍在查看其余问题。 就像约翰说的那样,根据您要删除的成员的类型,在 gsutil 命令上将“用户”更改为“服务帐户”。请记住,如果未找到该成员(更改实际上不会导致任何更改),您将收到“未进行更改”的消息不是错误,而是您的命令没有导致任何更改的警报。此外,您的 Java 代码在 removeBucketIamMember (第二行)上的“Identity identity”之后缺少结束“)”您的 Java 代码给您带来了哪个错误?。 我想我已经找到了问题的根源,我已将其作为答案发布 【参考方案1】:

我在您的代码中发现了问题。虽然我不能完全确定这是唯一的问题,因为我无法编译您的代码,但我也必须更改几个类。

在我能够编译并运行代码后,我注意到即使执行了“删除”功能,也没有真正发生任何事情,在进行了几次打印后,我注意到它试图使用错误的“角色删除服务帐户” ",因为您正在更改 "for" 循环上的 "role" 值,并且如果 "set" 不等于 "attacker-service-account",则循环进行另一次迭代并更改 "role" 值。

这是我的类的代码(对示例 sn-p 的修改):

package com.google.cloud.examples.storage.snippets;

import com.google.cloud.Identity;
import com.google.cloud.Policy;
import com.google.cloud.Role;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;
import com.google.cloud.storage.StorageRoles;
import java.util.Map;
import java.util.Set;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/** This class contains Bucket-level IAM snippets for the @link Storage interface. */
public class BucketIamSnippets 

  /** Example of listing the Bucket-Level IAM Roles and Members */
  public Policy listBucketIamMembers(String bucketName) 
    // [START view_bucket_iam_members]
    // Initialize a Cloud Storage client
    Storage storage = StorageOptions.getDefaultInstance().getService();

    // Get IAM Policy for a bucket
    Policy policy = storage.getIamPolicy(bucketName);

    // Print Roles and its identities
    Map<Role, Set<Identity>> policyBindings = policy.getBindings();
    for (Map.Entry<Role, Set<Identity>> entry : policyBindings.entrySet()) 
      System.out.printf("Role: %s Identities: %s\n", entry.getKey(), entry.getValue());
    
    // [END view_bucket_iam_members]
    return policy;
  

  /** Example of adding a member to the Bucket-level IAM */
  public Policy addBucketIamMember(String bucketName, Role role, Identity identity) 
    // [START add_bucket_iam_member]
    // Initialize a Cloud Storage client
    Storage storage = StorageOptions.getDefaultInstance().getService();

    // Get IAM Policy for a bucket
    Policy policy = storage.getIamPolicy(bucketName);

    // Add identity to Bucket-level IAM role
    Policy updatedPolicy =
        storage.setIamPolicy(bucketName, policy.toBuilder().addIdentity(role, identity).build());

    if (updatedPolicy.getBindings().get(role).contains(identity)) 
      System.out.printf("Added %s with role %s to %s\n", identity, role, bucketName);
    
    // [END add_bucket_iam_member]
    return updatedPolicy;
  


  public static void removeUserFromBucketUsingEmail(String bucketName, Role role, String email)  

        Storage storage = StorageOptions.getDefaultInstance().getService(); 
        Policy policy = storage.getIamPolicy(bucketName);
        Identity identity = Identity.serviceAccount(email);
        String eTag = policy.getEtag();
        System.out.println("etag: " + eTag);

        Policy updatedPolicy = storage.setIamPolicy(bucketName, policy.toBuilder().removeIdentity(role, identity).build());

    if (updatedPolicy.getBindings().get(role) == null
        || !updatedPolicy.getBindings().get(role).contains(identity)) 
      System.out.printf("Removed %s with role %s from %s\n", identity, role, bucketName);
    


    


public static void main(String... args) throws Exception 

    try
    

    String bucketName = "my-bucket-name";

    BucketIamSnippets obj = new BucketIamSnippets ();
    Role role_admin = StorageRoles.objectAdmin();

    String acc_1 = "test1@my.iam.gserviceaccount.com";
    String acc_2 = "test2@my.iam.gserviceaccount.com";
    Identity identity_1 = Identity.serviceAccount(acc_1);
    Identity identity_2 = Identity.serviceAccount(acc_2);

     System.out.println(obj.addBucketIamMember (bucketName, role_admin, identity_1 ));
     System.out.println(obj.addBucketIamMember (bucketName, role_admin, identity_2 ));


      Storage storage = StorageOptions.getDefaultInstance().getService();
        Policy policy = storage.getIamPolicy(bucketName);
        System.out.println(policy);

        //List<Role> roleList = new ArrayList<>();
        List<Set<Identity>> identities = new ArrayList<>();
        // Print Roles and its identities
        Set<Identity> wrongIdentities = new HashSet<Identity>();
        Role aux = null;

        Map<Role, Set<Identity>> policyBindings = policy.getBindings();
        Set<Identity> setidentities = new HashSet<>();
        for (Map.Entry<Role, Set<Identity>> entry : policyBindings.entrySet()) 
            aux = entry.getKey();
            System.out.println("role plain " + aux);
            System.out.println("role other  " + aux.getValue());

            if (aux.getValue().equals("roles/storage.objectAdmin")) 
                System.out.println("role :" + aux.getValue());
                System.out.println("Identities getV :" + entry.getValue());
                System.out.println("Identities getK :" + entry.getKey());

                setidentities = entry.getValue();
                System.out.println("setidentities  :" + setidentities);
                System.out.println("setidentities size :" + setidentities.size());
                for (Identity set : setidentities) 
                    if ((set.equals("serviceAccount: test2@my.iam.gserviceaccount.com"))) 
                        System.out.println("strong one : " + set);
                        continue;
                     else 
                        wrongIdentities.add(set);
                        System.out.println("strong one : " + set);

                    

                    System.out.println("wrongIdentities.size() : " + wrongIdentities.size());

                
            

        

        System.out.println("ww " + wrongIdentities);
        System.out.println("policyEtag " + policy.getEtag());
        //GCSFunctions function = new GCSFunctions(); 

        for (Identity identity : wrongIdentities) 
            BucketIamSnippets.removeUserFromBucketUsingEmail(bucketName, role_admin, identity.getValue());
        


    
    catch (Exception e)
    
        e.printStackTrace ();
    



注意事项:

    我添加了两个测试服务帐户,然后运行您的代码(稍作修改)。 我已将“角色”直接初始化为 objectAdmin,这就是我传递给删除函数的内容。 修改代码以符合您的实际用例。 我已经用 example 上使用的相同依赖项编译了它

【讨论】:

非常感谢,您准确无误。你是genius!该代码现在运行良好。 roles 设置不正确,您还展示了如何初始化角色以使其保持不变,例如roles/storage.objectAdmin. 很高兴知道它对您有帮助:)

以上是关于从 Google 存储桶 IAM 政策中删除用户(身份)不起作用的主要内容,如果未能解决你的问题,请参考以下文章

AWS:将 IAM 用户限制在 S3 存储桶中的特定文件夹

仅允许从 S3 存储桶的特定文件夹中删除的 IAM 策略

为访问多个 s3 存储桶指定正确的 IAM 权限

针对 Grafana 警报写入 s3 存储桶的 AWS IAM 策略问题

如何在不创建 IAM 用户的情况下将文件从 EKS 上传到 S3 存储桶?

如何将 S3 存储桶锁定到特定用户和 IAM 角色