The process of adding service accounts to a specific role in a GCP project involves:
- Get the current IAM policy.
- Modify the policy to add the new service accounts to the desired role.
- Set the updated IAM policy.
Based on your code, it seems you've followed these steps, but there are some issues with the manipulation of the policy and setting it. Let's refine your code:
- Use the correct client for IAM operations.
resourcemanager_v3.ProjectsClient
is for Project resource operations. You need to use IAM
clients.
- Make sure you're using the right method and service client for your use case. For projects, use
projects().getIamPolicy
and projects().setIamPolicy
.
- Ensure you're modifying the IAM policy correctly.
Here's an adjusted code sample:
from google.cloud import resource_manager
from google.auth.credentials import Credentials
from google.iam.v1 import iam_policy_pb2
# Assuming your credentials object is correctly initialized
client = resource_manager.Client(credentials=credentials)
project_id = "YOUR_PROJECT_ID"
# Get the current IAM policy for the project
policy = client.get_project(project_id).get_iam_policy()
projects_to_add = [
f"serviceAccount:service-{proj}@serverless-robot-prod.iam.gserviceaccount.com"
for proj in proj_numbers
if proj not in storage_obj_viewer_list
]
# Check if the role exists in the policy, if not add it
role_exists = False
for binding in policy["bindings"]:
if binding["role"] == "roles/storage.objectViewer":
# Add the new members to the existing role
binding["members"].extend(projects_to_add)
role_exists = True
if not role_exists:
# If the role doesn't exist in the policy, add it with the new members
policy["bindings"].append({
"role": "roles/storage.objectViewer",
"members": projects_to_add
})
# Set the updated IAM policy
client.get_project(project_id).set_iam_policy(policy)
The error "object is not subscriptable" typically arises when trying to use indexing (e.g., using brackets like obj[key]
) on an object that does not support it.
Given your error, it seems the current_policy
object returned by the get_iam_policy
call isn't directly subscriptable. Instead, you should be working with the dictionary version (roles_dict
), then convert it back to a proto message before setting the policy.
Here's how you can convert the modified roles_dict
back to a policy object and then set it:
First, you need to import ParseDict
from google.protobuf.json_format
.
Convert the dictionary (roles_dict
) back to the policy object.
Make the set_iam_policy
call.
Here's a continuation of the code from before:
from google.protobuf.json_format import ParseDict
# ... [rest of your code]
# Convert the modified roles_dict back to a Policy object
modified_policy = iam_policy_pb2.Policy()
ParseDict(roles_dict, modified_policy)
# Set the modified policy
req = iam_policy_pb2.SetIamPolicyRequest(
resource="projects/mse-sandbox-registry-anushka",
policy=modified_policy
)
response = client.set_iam_policy(request=req)
This should work without the "not subscriptable" error since you're now manipulating the dictionary representation of the policy and converting it back to a proto message when required.
If you're looking to remove members from the members_list
, you can use Python's built-in list methods.
To remove specific members from the list:
Using remove
:
The remove()
method removes the first occurrence of the value.
members_list.remove(member_to_remove)
This will raise a ValueError
if the member doesn't exist, so it's typically wrapped in a try-except block:
try:
members_list.remove(member_to_remove)
except ValueError:
pass # or handle as you see fit
Using List Comprehension:
This is useful if you want to remove multiple members or if you're not sure whether the member exists in the list.
members_to_remove = ['member1', 'member2', ...]
members_list = [member for member in members_list if member not in members_to_remove]
After you've modified the members_list
by either adding or removing members, you can continue with your existing code to convert the roles_dict
back to a proto message and set the IAM policy.