Michael
Michael

Reputation: 1728

Domain wide delegation with default credentials in Cloud Run

In golang I'd like to use default service account credentials provided by Cloud Run to create delegated credentials (domain-wide delegation), specifically to invoke the Drive API as the user. I've got this working when the credentials are obtained from a json file, but not when provided by Cloud Run. I had the same problem in Python and followed this example to solve it, but am not sure how to do this in go.

Code example (gin handler) that works when loading from JSON file (service account key with domain-wide delegation) but not when deriving credentials from Cloud Run:

email := "[email protected]"
params := google.CredentialsParams{
    Scopes:  []string{"https://www.googleapis.com/auth/drive.readonly"},
    Subject: email}
creds, credErr := google.FindDefaultCredentialsWithParams(c, params)
if credErr != nil {
    msg := fmt.Sprintf("Unable to create credentials as %v: %v", email, credErr)
    fmt.Println(msg)
    c.String(http.StatusInternalServerError, msg)
    return
}

// CREATE DRIVE SERVICE
client := oauth2.NewClient(c, creds.TokenSource)
driveService, driveErr := drive.NewService(c, option.WithHTTPClient(client))
if driveErr != nil {
    msg := fmt.Sprintf("Unable to retrieve Drive client: %v", driveErr)
    fmt.Println(msg)
    c.String(http.StatusInternalServerError, msg)
    return
}

// List Files
r, listErr := driveService.Files.List().PageSize(10).Do()
if listErr != nil {
    log.Fatal(listErr)
}
fmt.Printf("Received %v files\n", len(r.Files))
for _, i := range r.Files {
    fmt.Println(i.Name)
}
c.String(http.StatusOK, "Ok")
return

When I run this from JSON file, it lists the ten file names from [email protected]. When I run this in Cloud Run (without including the JSON file in the container), it doesn't find any files, and I believe this is because the credentials are not user credentials, but rather service account credentials without access to any files.

Upvotes: 4

Views: 635

Answers (1)

Johannes Passing
Johannes Passing

Reputation: 2805

To use domain-wide delegation without a service account key you have to:

  1. Create a JWT assertion for impersonating a user
  2. Call projects.serviceAccounts.signJwt on a service account that's configured for domain-wide delegation to sign the assertion
  3. Exchange the signed assertion against an access token

This blog post and this question have more details.

Upvotes: 2

Related Questions