1
votes

I have been trying to use the api to create service accounts in GCP.

To create a service account I send the following post request:

base_url = f"https://iam.googleapis.com/v1/projects/{project}/serviceAccounts"
auth = f"?access_token={access_token}"
data = {"accountId": name}
# Create a service Account
r = requests.post(base_url + auth, json=data)

this returns a 200 and creates a service account:

Then, this is the code that I use to create the specific roles:

sa = f"{name}@dotmudus-service.iam.gserviceaccount.com"
sa_url = base_url + f'/{sa}:setIamPolicy' + auth
data = {"policy":
    {"bindings": [
        {
            "role": roles,
            "members":
                [
                    f"serviceAccount:{sa}"
                ]
        }
    ]}
}

If roles is set to one of roles/viewer, roles/editor or roles/owner this approach does work. However, if I want to use, specifically roles/cloudsql.viewer The api tells me that this option is not supported.

Here are the roles. https://cloud.google.com/iam/docs/understanding-roles

I don't want to give this service account full viewer rights to my project, it's against the principle of least privilege.

How can I set specific roles from the api?

EDIT:

here is the response using the resource manager api: with roles/cloudsql.admin as the role

POST https://cloudresourcemanager.googleapis.com/v1/projects/{project}:setIamPolicy?key={YOUR_API_KEY}

{
 "policy": {
  "bindings": [
   {
    "members": [
     "serviceAccount:sa@{project}.iam.gserviceaccount.com"
    ],
    "role": "roles/cloudsql.viewer"
   }
  ]
 }
}


{
  "error": {
    "code": 400,
    "message": "Request contains an invalid argument.",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.cloudresourcemanager.projects.v1beta1.ProjectIamPolicyError",
        "type": "SOLO_REQUIRE_TOS_ACCEPTOR",
        "role": "roles/owner"
      }
    ]
  }
}
1
I am facing the same problem here. How did you solved this problem?Pedro Ghilardi
I solved this by extracting the entire policy object via, roles.get. Then appending the required role to the object and calling this api with data = the entire json object.Daniel Lee

1 Answers

1
votes

With the code provided it appears that you are appending to the first base_url which is not the correct context to modify project roles.

This will try to place the appended path to: https://iam.googleapis.com/v1/projects/{project}/serviceAccount

The POST path for adding roles needs to be: https://cloudresourcemanager.googleapis.com/v1/projects/{project]:setIamPolicy

If you remove /serviceAccounts from the base_url and it should work.

Edited response to add more information due to your edit

OK, I see the issue here, sorry but I had to set up a new project to test this.

cloudresourcemanager.projects.setIamPolicy needs to replace the entire policy. It appears that you can add constraints to what you change but that you have to submit a complete policy in json for the project.

Note that gcloud has a --log-http option that will help you dig through some of these issues. If you run

gcloud projects add-iam-policy-binding $PROJECT --member serviceAccount:$NAME --role roles/cloudsql.viewer --log-http 

It will show you how it pulls the existing existing policy, appends the new role and adds it.

I would recommend using the example code provided here to make these changes if you don't want to use gcloud or the console to add the role to the user as this could impact the entire project.

Hopefully they improve the API for this need.