  def GetBucketACLs(self,
                    bucket: str,
                    user_project: Optional[str] = None) -> Dict[str, List[str]]:
    """Get ACLs for a Google Cloud Storage bucket.

    This includes both ACL entries and IAM policies.

    Args:
      bucket (str): Name of a bucket in GCS.
          Ex: logs_bucket_1
      user_project (str): The project ID to be billed for this request.
          Required for Requester Pays buckets.

    Returns:
      Dict: A mapping of role to members of that role.
    """
    ret = collections.defaultdict(list)
    if bucket.startswith('gs://'):
      # Can change to removeprefix() in 3.9
      bucket = bucket[5:]
    gcs_bac = self.GcsApi().bucketAccessControls() # pylint: disable=no-member
    request = gcs_bac.list(bucket=bucket, userProject=user_project)
    # https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls#resource
    ac_response = request.execute()
    for item in ac_response.get('items', []):
      if item.get('kind') == 'storage#bucketAccessControl':  # Sanity check
        ret[item['role']].append(item['entity'])
    gcs_buckets = self.GcsApi().buckets() # pylint: disable=no-member
    request = gcs_buckets.getIamPolicy(bucket=bucket)
    # https://cloud.google.com/storage/docs/json_api/v1/buckets/getIamPolicy
    iam_response = request.execute()
    for item in iam_response.get('bindings', []):
      for member in item.get('members', []):
        ret[item['role']].append(member)
    return ret
Get ACLs for a Google Cloud Storage bucket.

This includes both ACL entries and IAM policies.

Args:
bucket (str): Name of a bucket in GCS.
Ex: logs_bucket_1
user_project (str): The project ID to be billed for this request.
Required for Requester Pays buckets.

Returns:
Dict: A mapping of role to members of that role.
libcloudforensics/providers/gcp/internal/storage.py