2

Goal

Assign a role dialogflow.admin to a service account I created for a project using the Node.js Client library for Google APIs.

Issue

When I try to update my service accounts IAM Policy and add a role to the service account. I get an error that the role is not supported for this resource type.

I am trying to give my service account the Dialogflow API Admin Role roles/dialogflow.admin

The method in the Node.js client library I am using is iam.projects.serviceAccounts.setIamPolicy.

I have already managed to create the service account with this Node.js client library with a function shown here.

async function createServiceAccount(projectID, serviceAccountID){
    const authClient = await auth.getClient();
    var request = {
        name: "projects/"+projectID,
        resource: {
        "accountId": serviceAccountID,
        "serviceAccount": {
            "description" : "Service Account for project: "+projectID+" for DialogFlow authentication with VA",
            "displayName": "VA Dialogflow Service Account "+projectID
        }
      },
      
      auth: authClient,
    };
  
    await iam.projects.serviceAccounts.create(request, function(err, response) {
      if (err) {
        console.error(err);
        return;
      }
       console.log(JSON.stringify(response, null, 2));
    });
}

after this function runs, and I am sure the service account is created, I run my function that is meant to set the roles of this service account.

async function setServiceAccountRoles(projectID, serviceAccountID){
    const authClient = await auth.getClient();
    var request = {
        resource_: "projects/"+projectID+"/serviceAccounts/"+serviceAccountID,
        resource: {
            policy: {
                bindings: [
                    {
                        // role: "projects/"+projectID+"roles/dialogflow.admin",
                        role: "roles/dialogflow.admin",
                        "members": [
                            "serviceAccount:"+serviceAccountID
                        ]
                    }
                    ],
                    version: 1
            }
        },
      
      auth: authClient,
    };
  
    await iam.projects.serviceAccounts.setIamPolicy(request, function(err, response) {
      if (err) {
        console.error(err);
        return;
      }
       console.log(JSON.stringify(response, null, 2));
    });
}

Error

When I run this function I am give this error:

  code: 400,
  errors: [
    {
      message: 'Role roles/dialogflow.admin is not supported for this resource.',
      domain: 'global',
      reason: 'badRequest'
    }
  ]

I have used these following resources to get this far: https://cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts/setIamPolicy

https://cloud.google.com/iam/docs/reference/rest/v1/Policy

https://cloud.google.com/iam/docs/granting-changing-revoking-access#granting_access_to_a_service_account_for_a_resource

Alternative methods.

I have tried changing the role to a project specific path like this:

async function setServiceAccountRoles(projectID, serviceAccountID){
    const authClient = await auth.getClient();
    var request = {
        resource_: "projects/"+projectID+"/serviceAccounts/"+serviceAccountID,
        resource: {
            policy: {
                bindings: [
                    {
                        role: "projects/"+projectID+"roles/dialogflow.admin",
                        "members": [
                            "serviceAccount:"+serviceAccountID
                        ]
                    }
                    ],
                    version: 1
            }
        },
      
      auth: authClient,
    };
  
    await iam.projects.serviceAccounts.setIamPolicy(request, function(err, response) {
      if (err) {
        console.error(err);
        return;
      }
       console.log(JSON.stringify(response, null, 2));
    });
}

however, with this I get the error : message: "Role (projects/va-9986d601/roles/dialogflow.admin) does not exist in the resource's hierarchy.",

Is it possible that the only way to update my service account's roles and permission is through the console or gcloud commands? If so, is there any recommended ways of running said gcloud commands through the node.js client library or from a node application itself?

Gene
  • 104
  • 15

1 Answers1

2

You are trying to set an IAM policy on the service account. That is used to grant other identities access to the service account itself.

You should modify the IAM binding for the project and not for the service account.

Use the getIamPolicy and setIamPolicy. Examples are included with the documentation.

WARNING: be very careful writing code that modifies a project's bindings. If you overwrite the bindings you can easily lock yourself out of your project. Then you would need to open a paid support ticket with Google Cloud Support. Practice with a throw away project.

John Hanley
  • 74,467
  • 6
  • 95
  • 159
  • This has definitely got me on the right track, thank you. I am getting a `PERMISSION_DENIED` error when trying to use the setIamPolicy method you linked... the service account I an using to authenticate my whole node.js app with has owner permissions of the organization I'm creating these projects in.. Do you know if there is a specific permission to turn on for this use case? I can't find an exact requirement in this documeantion. – Gene Feb 08 '22 at 19:42
  • @gene - The IAM role **Owner** has the correct permissions. This means that the service account you are using does not have the permissions you think it has. Create a new question if you have a permissions problem as your original question has been answered. Note: the service account needs the IAM role **roles/resourcemanager.projectIamAdmin** or similar. https://cloud.google.com/iam/docs/granting-changing-revoking-access – John Hanley Feb 08 '22 at 19:46