Linda Lawton - DaImTo
Linda Lawton - DaImTo

Reputation: 116888

Service account delegation with Google workspace - Entity Not found

I am trying to access the Google Directory api as a test this method domains.list using a service account.

If I use the try me on that page logging in with my domain admin email. It works and I get a response back. So the method and the customer id i am passing should be working.

I followed the instructions here Perform Google Workspace Domain-Wide Delegation of Authority to create a service account and enable domain wide delegation.

If I check both my workspace account and Google cloud console. The delegation appears to be configured. with my domain admin email set as principle.

My code:

namespace Daimto.Sample.WorkspaceAdmin
{
    class Program
    {
        private static readonly string[] Scopes = {DirectoryService.Scope.AdminDirectoryDomain};
        private static readonly string PathToServiceAccountKeyFile = @"C:\YouTube\workspaceserviceaccount-e4823a933ae3.json";
        private static readonly string CustomerId = "C01lp3chxa";
        private static readonly string workspaceAdmin = "[email protected]";

        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            var credential = LoadGoogleCredentails();
            var service = CreateDirectoryService(credential);
            var request = service.Domains.List(CustomerId);
            var result = request.Execute();
            foreach (var domain in result.Domains)
            {
                Console.WriteLine(domain.DomainName);
            }
        }

        private static DirectoryService CreateDirectoryService(GoogleCredential credential)
        {
            return new (new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "Daimto Testing Workspace with service account"
                }
            );
        }

        private static GoogleCredential LoadGoogleCredentails()
        {
            return GoogleCredential.FromFile(PathToServiceAccountKeyFile)
                .Impersonate(new ImpersonatedCredential.Initializer(workspaceAdmin))
                .CreateScoped(Scopes);
        }
    }
}

error

Running code as it appears above.

 "error": {
    "code": 404,
    "message": "Requested entity was not found.",
    "errors": [
      {
        "message": "Requested entity was not found.",
        "domain": "global",
        "reason": "notFound"
      }

Not found implies to me that its not even able to access the domain.

However if I remove the line for impersonation. Then I get this error

Not Authorized to access this resource/api [403]
Errors [
  Message[Not Authorized to access this resource/api] Location[ - ] Reason[forbidden] Domain[global]
]

This implies to me that without the impersonation it doesn't have access.

So I am confused. With impersonation it cant find it, without impersonation it can find it but doesn't have access?

The only clue I can find in the documentation is this started note.

enter image description here

So what exactly do they mean by this Only users with access to the Admin APIs can access the Admin SDK Directory API I am admin shouldn't i have access? Should access be configured if so where?

Upvotes: 1

Views: 567

Answers (1)

Linda Lawton - DaImTo
Linda Lawton - DaImTo

Reputation: 116888

Ok this required a lot of digging.

There are two methods in the Google .Net client library Impersonate() and CreateWithUser()

Impersonate Allows this credential to impersonate the ImpersonatedCredential.Initializer.TargetPrincipal. Only ServiceAccountCredentialand UserCredential support impersonation, so this method will throw <see InvalidOperationException if this credential's UnderlyingCredential is not of one of those supported types.

while

CreateWithUser If the credential supports Domain Wide Delegation, this method creates a copy of the credential with the specified user. Otherwise, it throws <see InvalidOperationException. At the moment only ServiceAccountCredential supports Domain Wide Delegation.

So the key here is are you trying to delegate to a user or impersonate a user. There is a difference.

So by using CreateWithUser it now works.

 private static GoogleCredential LoadGoogleCredentails()
        {
            return GoogleCredential.FromFile(PathToServiceAccountKeyFile)
                .CreateScoped(Scopes)
                .CreateWithUser(workspaceAdmin);
        }

Upvotes: 2

Related Questions