Deletion of users (identities) from Google bucket

2019-08-26 09:15发布

问题:

In order to remove identities from a google cloud bucket, I use the example provided at the GCP examples repo: here. I am wondering if there is something I am missing, I have the correct root credentials to the cloud account, as well as the project ownership credentials. Basically, the removal operations do not owrk both from Java code and using the gsutil function from gcp web console.

Here is the original policy:

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
 }

Here is the second policy version, before writing to 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
}

Here is my code snippet:

Read bucket policy and extract unwanted identities

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));
    }
 }

Remove Unwanted Identities from policy

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;
}

Update 01 I tried also using gsutil from within the web console, still does not work.

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/

Update 02 As advised by @JohnHanley, gsutil worked after I replaced user with serviceAccount. However, the java code is not yet working.

回答1:

I have found the issue in your code. Although I cannot be completely sure that this was the only issue since I wasn't able to compile your code, I had to change several classes too.

After I was able to compile and run the code I noticed that even if the "remove" function was executed nothing really happened, after making a few prints I noticed that it was trying to remove the services accounts using the wrong "role", since you were changing the "role" value on the "for" loop, and if the "set" wasn't equal to "attacker-service-account" then the loop made another iteration and changed the "role" value.

Here's the code of my class (a modification of the example snippet):

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 ();
    }
}

}

Notes:

  1. I add two test services accounts and then I run your code (with a little modifications).
  2. I have initialized the "role" as objectAdmin directly, and that's what i pass to the removing function.
  3. Modify the code to comply with your actual use case.
  4. I have compiled this with the same dependencies used on the example