Search code examples
google-cloud-platformterraformgoogle-iam

GCP API - Determining what role an resource instance has been created with


For the project I'm on, I am tasked with creating a testing app that uses Terraform to create a resource instance and then test that it was created properly. The purpose is testing the Terraform Script result by validating certain characteristics of the resource created. That's the broad outline.

For several of these scripts a resource is assigned a role. It could be a PubSub subscription, DataCatalog, etc.

Example Terraform code for a Spanner Database assigning roles/spanner.databaseAdmin:

resource "google_spanner_database_iam_member" "user_database_admin" {
  for_each = toset(var.iam_user_database_admins)
  project = var.project
  instance = var.instance_id
  database = google_spanner_database.spanner_database.name
  role       = "roles/spanner.databaseAdmin"
  member     =  "user:${each.key}"
}

So my question is this: Is there a way using a .NET GCP API to make a call to determine that the role was assigned? I can test for permissions via a TestIamPermissions method off of the client object and that's what I'm currently doing. But that gives me a sometimes long list of possible permissions. Is there a way to say "does this spanner database have the roles/spanner.databaseAdmin assigned?"

Here's an example of code testing for permissions on a PubSub Subscription:

TestIamPermissionsRequest subscriptionRequest = new TestIamPermissionsRequest
{
    ResourceAsResourceName = SubscriptionName.FromProjectSubscription(projectId, subscriptionId),
    Permissions = {
        "pubsub.subscriptions.get",
        "pubsub.subscriptions.delete",
        "pubsub.subscriptions.update"
    }
};
TestIamPermissionsResponse subscriptionResponse = publisher.TestIamPermissions(subscriptionRequest);

Seems like there ought to be a cleaner way to do this, but being somewhat new to GCP, I haven't found a way yet. Suggestions will be welcome.


Solution

  • Thought I should close this question off with what I eventually discovered. The proper question isn't what role is assigned an instance of a resource, but what users have been allowed to use the resource and with what role.

    The proper call is GetIamPolicy which is available in the APIs for all of the resources that I've been working with. The problem was that I wasn't seeing anything due to no user accounts being assigned to the resource. I updated the Terraform script to assign a user to the resource with the required roles. When calling GetIamPolicy, it returns an array in the Bindings that lists roles and users that are assigned. This was the information I needed. Going down the path of using TestIamPermissions was unneeded.

    Here's an example my use of this:

                bool roleFound = false;
                bool userFound = false;
                bool exception = false;
                try
                {
                    Policy policyResponse = Client.GetIamPolicy(Resource);
                    var bindings = policyResponse.Bindings;
                    foreach (var item in bindings)
                    {
                        if (AcceptedRoles.Contains(item.Role))
                            roleFound = true;
    
                        foreach (var user in item.Members)
                        {
                            string testUser = user;
                            if (user.Substring(0, 5) == "user:")
                            {
                                testUser = user.Substring(5);
                            }
                            else if (user.Substring(0, 6) == "group:")
                            {
                                testUser = user.Substring(6);
                            }
                            if (Settings.UserTestList.Contains(testUser))
                                userFound = true;
                        }
                    }
                }
                catch (Grpc.Core.RpcException)
                {
                    exception = true;
                }
    
                Assert.True(roleFound);
                Assert.True(userFound);
                Assert.False(exception);