A brief summary: I have a PHP web application which uses the Google Cloud PHP Client SDK to integrate with Dialogflow. That’s working no problem. I have a need now to let my users access the GCP Dialogflow dashboard directly, and part of that means that they need to be able to add/remove the Dialogflow permissions to users from within my application. (For obvious reasons I don’t want to give them full project IAM permissions and access).
Apparently, permissions are handled by a separate “Google APIs Client Library for PHP”.
This appears to be the API for listing the existing project user policies: https://cloud.google.com/resource-manager/reference/rest/v1/projects/listOrgPolicies
I believe that this is the API for the add/remove users part, but it’s not that obvious: https://cloud.google.com/resource-manager/reference/rest/v1/projects/setIamPolicy
===
The problem:
However, when I run the example code provided in the above referenced listOrgPolicies API, I get this error:
PHP Fatal error: Uncaught Error: Class 'Google_Service_CloudResourceManager_ListOrgPoliciesRequest' not found
I tried both composer require google/apiclient-services
and composer require google/apiclient-services:dev-master
. And got the same result.
===
My questions are:
Are these even the correct APIs for the task?
Where can I find the SDK libraries for these actions? (or alternatively, if anyone has suggestions on how to perform these tasks directly to the API using PHP cURL without the SDK)
I’d prefer if all the action happens in PHP, but if you have a working solution using some other method or language or console command line, as long as it can be executed by my application I can work with that.
Thanks in advance!
Advertisement
Answer
Before getting to the answer, please make sure the Resource Manager API is enabled. This is necessary for the REST approach and the programmatic one.
To modify the IAM bindings for a user in a given project there are two endpoints that need to be called, which are documented here. Those would be:
- To get the current IAM configuration: https://cloud.google.com/resource-manager/reference/rest/v1/projects/getIamPolicy
- To set the new IAM policy: https://cloud.google.com/resource-manager/reference/rest/v1/projects/setIamPolicy
In between steps 1 and 2 it would be needed to modify the json returned by the first endpoint either adding the user with the role of your choice or removing the user entry from it. To see what’s the json structure required to add/remove users I would suggest examining the link shared above as well as examining the payload returned by the first command.
While directly calling the REST api is one option at your disposal you may also use the gcloud CLI to perform such operations. As it seems users are going to be added/removed one by one the command line would be a simple choice and it’s the one requiring less setup. The commands for both actions would be:
/ To add user role gcloud projects add-iam-policy-binding PROJECT_ID --member=user:somebody@example.com --role=roles/viewer / To remove user role gcloud projects remove-iam-policy-binding PROJECT_ID --member=user:somebody@example.com --role=roles/viewer
The third option would be to do it programmatically. Although I would like to provide a PHP sample I don’t have enough experience with the language, nonetheless below is a Python script that allows to add/remove roles. It has been bootstrapped from the Quickstart with just some minor changes and from the tests I ran it should work fine.
# TODO: Install required libraries # pip3 install --upgrade google-api-python-client google-auth google-auth-httplib2 import os from google.oauth2 import service_account import googleapiclient.discovery def get_policy(crm_service, project_id, version=3): """Gets IAM policy for a project.""" policy = ( crm_service.projects() .getIamPolicy( resource=project_id, body={"options": {"requestedPolicyVersion": version}}, ) .execute() ) print(policy) return policy def set_policy(crm_service, project_id, policy): """Sets IAM policy for a project.""" policy = ( crm_service.projects() .setIamPolicy(resource=project_id, body={"policy": policy}) .execute() ) return policy def initialize_service(): """ Initializes a Cloud Resource Manager service. The Environemnt variable GOOGLE_APPLICATION_CREDENTIALS must point to the service account key.json file """ credentials = service_account.Credentials.from_service_account_file( filename=os.environ["GOOGLE_APPLICATION_CREDENTIALS"], scopes=["https://www.googleapis.com/auth/cloud-platform"], ) crm_service = googleapiclient.discovery.build( "cloudresourcemanager", "v1", credentials=credentials ) return crm_service def modify_policy_add_role(crm_service, project_id, role, member): """Adds a new role binding to a policy.""" policy = get_policy(crm_service, project_id) binding = None for b in policy["bindings"]: if b["role"] == role: binding = b break if binding is not None and member not in binding["members"]: binding["members"].append(member) else: binding = {"role": role, "members": [member]} policy["bindings"].append(binding) policy = set_policy(crm_service, project_id, policy) def modify_policy_remove_member(crm_service, project_id, role, member): """Removes a member from a role binding.""" policy = get_policy(crm_service, project_id) # The try-except below handles the case where the role isn't in the IAM policy try: binding = next(b for b in policy["bindings"] if b["role"] == role) except StopIteration: print("The role is not included in the IAM policy. Can't remove user") raise KeyError if "members" in binding and member in binding["members"]: binding["members"].remove(member) set_policy(crm_service, project_id, policy) if __name__ == '__main__': # TODO: Replace with your project ID project_id = "projectID" # TODO: Replace with the ID of your member in the form 'user:member@example.com'. member = "user:somebody@example.com" # TODO: Replace the role with the role you want to grant/remove role = "roles/logging.logWriter" # Initializes the client. crm_service = initialize_service() # Call modify_policy_add_role or modify_policy_remove_member as required modify_policy_add_role(crm_service, project_id, role, member) modify_policy_remove_member(crm_service, project_id, role, member)