Skip to content

Instantly share code, notes, and snippets.

Revisions

  1. @salrashid123 salrashid123 revised this gist Oct 13, 2023. No changes.
  2. @salrashid123 salrashid123 revised this gist Oct 13, 2023. 1 changed file with 17 additions and 0 deletions.
    17 changes: 17 additions & 0 deletions workload_federation_dwd.go
    Original file line number Diff line number Diff line change
    @@ -71,6 +71,23 @@ 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: "admin@yourdomain.com",
    // }, option.WithCredentialsJSON([]byte(c1_adc)))


    ts, err := impersonate.CredentialsTokenSource(ctx, impersonate.CredentialsConfig{
    TargetPrincipal: "tpm-sa@$PROJECT_ID.iam.gserviceaccount.com",
  3. @salrashid123 salrashid123 created this gist Oct 13, 2023.
    148 changes: 148 additions & 0 deletions workload_federation_dwd.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,148 @@
    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/alice@domain.com \
    --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()

    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: "admin@esodemoapp2.com",
    })
    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.")
    }

    }