Skip to content

Instantly share code, notes, and snippets.

@salrashid123
Last active January 30, 2025 01:24
Show Gist options
  • Save salrashid123/a7e8c9043d27cb0478b36cf0303a2f20 to your computer and use it in GitHub Desktop.
Save salrashid123/a7e8c9043d27cb0478b36cf0303a2f20 to your computer and use it in GitHub Desktop.
Access GCP and workspace APIs using GCP Workload Identity Federation usign Domain Delegation
package main
import (
"fmt"
"log"
"context"
"cloud.google.com/go/storage"
admin "google.golang.org/api/admin/directory/v1"
driveactivity "google.golang.org/api/driveactivity/v2"
"google.golang.org/api/impersonate"
"google.golang.org/api/iterator"
"google.golang.org/api/option"
)
/*
Access GCP and workspace APIs using GCP Workload Identity Federation
see
* https://blog.salrashid.dev/articles/2021/impersonation_and_domain_delegation/
* https://blog.salrashid.dev/articles/2021/understanding_workload_identity_federation/
* https://pkg.go.dev/google.golang.org/api/impersonate#example-CredentialsTokenSource-AdminUser
using fake oidc server here:
https://gist.github.com/salrashid123/677866e42cf2785fe885ae9d6130fc21
create an oidc token and set
$ cat sts-creds.json
{
"type": "external_account",
"audience": "//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/fake-oidc-pool-1/providers/fake-oidc-provider-1",
"subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
"token_url": "https://sts.googleapis.com/v1/token",
"credential_source": {
"file": "/tmp/oidccred.txt"
}
}
grant the candidate service account 'self-impersonation' permissions
$ gcloud iam service-accounts describe tpm-sa@$PROJECT_ID.iam.gserviceaccount.com
email: tpm-sa@$PROJECT_ID.iam.gserviceaccount.com
etag: MDEwMjE5MjA=
name: projects/$PROJECT_ID/serviceAccounts/tpm-sa@$PROJECT_ID.iam.gserviceaccount.com
oauth2ClientId: '100890260483227123113'
projectId: $PROJECT_ID
uniqueId: '100890260483227123113'
gcloud iam service-accounts \
add-iam-policy-binding tpm-sa@$PROJECT_ID.iam.gserviceaccount.com \
--member=principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/fake-oidc-pool-1/subject/[email protected] \
--role=roles/iam.serviceAccountTokenCreator
grant service account domain delegation rights to scopes
admin.AdminDirectoryUserReadonlyScope, driveactivity.DriveActivityReadonlyScope, "https://www.googleapis.com/auth/cloud-platform"
as described in: https://blog.salrashid.dev/articles/2021/impersonation_and_domain_delegation/
finally
export GOOGLE_APPLICATION_CREDENTIALS=`pwd`/sts-creds.json
go run main.go
*/
func main() {
ctx := context.Background()
// c1_adc := fmt.Sprintf(`{
// "type": "external_account",
// "audience": "%s",
// "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
// "token_url": "https://sts.googleapis.com/v1/token",
// "credential_source": {
// "file": "%s"
// }
// }`, "//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/fake-oidc-pool-1/providers/fake-oidc-provider-1", "/tmp/oidccred.txt")
// ts, err := impersonate.CredentialsTokenSource(ctx, impersonate.CredentialsConfig{
// TargetPrincipal: "tpm-sa@$PROJECT_ID.gserviceaccount.com",
// Scopes: []string{admin.AdminDirectoryUserReadonlyScope, driveactivity.DriveActivityReadonlyScope, "https://www.googleapis.com/auth/cloud-platform"},
// Subject: "[email protected]",
// }, option.WithCredentialsJSON([]byte(c1_adc)))
ts, err := impersonate.CredentialsTokenSource(ctx, impersonate.CredentialsConfig{
TargetPrincipal: "tpm-sa@$PROJECT_ID.iam.gserviceaccount.com",
Scopes: []string{admin.AdminDirectoryUserReadonlyScope, driveactivity.DriveActivityReadonlyScope, "https://www.googleapis.com/auth/cloud-platform"},
Subject: "[email protected]",
})
if err != nil {
log.Fatal(err)
}
storageClient, err := storage.NewClient(ctx, option.WithTokenSource(ts))
if err != nil {
log.Fatalf("%v", err)
}
bucketName := "some-bucket"
it := storageClient.Bucket(bucketName).Objects(ctx, nil)
for {
attrs, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Fatal(err)
}
log.Println(attrs.Name)
}
adminservice, err := admin.NewService(ctx, option.WithTokenSource(ts))
if err != nil {
log.Fatal(err)
}
srv := admin.NewUsersService(adminservice)
// gcloud organizations list
usersReport, err := srv.List().Customer("your_customer_id").MaxResults(10).OrderBy("email").Do()
if err != nil {
log.Fatal(err)
}
if len(usersReport.Users) == 0 {
fmt.Print("No users found.\n")
} else {
fmt.Print("Users:\n")
for _, u := range usersReport.Users {
fmt.Printf("%s (%s)\n", u.PrimaryEmail, u.Name.FullName)
}
}
dsrv, err := driveactivity.NewService(ctx, option.WithTokenSource(ts))
if err != nil {
log.Fatalf("Unable to retrieve driveactivity Client %v", err)
}
q := driveactivity.QueryDriveActivityRequest{PageSize: 10}
r, err := dsrv.Activity.Query(&q).Do()
if err != nil {
log.Fatalf("Unable to retrieve list of activities. %v", err)
}
fmt.Println("Recent Activity:")
if len(r.Activities) > 0 {
for _, a := range r.Activities {
for _, i := range a.Actors {
log.Printf("%s, \n", i.User.KnownUser.PersonName)
}
}
} else {
fmt.Print("No activity.")
}
}
@salrashid123
Copy link
Author

dwd

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment