Skip to content

Instantly share code, notes, and snippets.

@StevenACoffman
Forked from pdecat/gcs-signed-url-main.go
Created June 28, 2022 14:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StevenACoffman/34deeecf5b2dea478da2b08aa6229874 to your computer and use it in GitHub Desktop.
Save StevenACoffman/34deeecf5b2dea478da2b08aa6229874 to your computer and use it in GitHub Desktop.
Creating a GCS Signed URL without a Service Account Key from a GCE instance or a GKE Pod using Workload Identity
package main
import (
"context"
"flag"
"log"
"net/url"
"time"
"cloud.google.com/go/compute/metadata"
credentials "cloud.google.com/go/iam/credentials/apiv1"
"cloud.google.com/go/storage"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
credentialspb "google.golang.org/genproto/googleapis/iam/credentials/v1"
)
func main() {
var bucket string
var object string
var method string
flag.StringVar(&bucket, "bucket", "", "The bucket")
flag.StringVar(&object, "object", "", "The object in the bucket")
flag.StringVar(&method, "method", "GET", "The HTTP method to use")
flag.Parse()
log.Printf("bucket: %v", bucket)
log.Printf("object: %v", object)
log.Printf("method: %v", method)
creds, err := google.FindDefaultCredentials(oauth2.NoContext)
if err != nil {
log.Printf("Error while getting default credentials: %v", err)
return
}
token, err := creds.TokenSource.Token()
if err != nil {
log.Printf("Error while getting token: %v", err)
return
}
accountID, ok := token.Extra("oauth2.google.serviceAccount").(string)
if !ok {
log.Printf("Error while getting account ID: %v", err)
return
}
log.Printf("accountID: %v", accountID)
client, err := google.DefaultClient(oauth2.NoContext)
if err != nil {
log.Printf("Error while getting default client: %v", err)
return
}
computeMetadataClient := metadata.NewClient(client)
email, err := computeMetadataClient.Email(accountID)
if err != nil {
log.Printf("Error while getting email: %v", err)
return
}
log.Printf("email: %v", email)
projectID, err := computeMetadataClient.ProjectID()
if err != nil {
log.Printf("Error while getting project ID: %v", err)
return
}
log.Printf("projectID: %v", projectID)
sc := storage.SignedURLOptions{
GoogleAccessID: email,
Method: method,
Expires: time.Now().Add(60 * time.Second),
ContentType: "",
}
sc.SignBytes = func(payload []byte) ([]byte, error) {
ctx := context.Background()
credsClient, err := credentials.NewIamCredentialsClient(ctx)
if err != nil {
return nil, err
}
req := &credentialspb.SignBlobRequest{
Name: email,
Payload: payload,
}
res, err := credsClient.SignBlob(ctx, req)
if err != nil {
return nil, err
}
return res.SignedBlob, err
}
rawURL, err := storage.SignedURL(bucket, object, &sc)
if err != nil {
log.Printf("Error while generating GCS pre-signed URL: %v", err)
return
}
URL, err := url.Parse(rawURL)
if err != nil {
log.Printf("Error while parsing generated URL: %v", err)
return
}
log.Printf("URL to use with %v method: %v", method, URL)
return
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment