Forked from salrashid123/workload_federation_dwd.go
Created
January 30, 2025 01:24
-
-
Save StevenACoffman/3dc7e6acc818155eebd25daa3e29d7b4 to your computer and use it in GitHub Desktop.
Access GCP and workspace APIs using GCP Workload Identity Federation usign Domain Delegation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment