Skip to content

Instantly share code, notes, and snippets.

@salrashid123
Last active February 15, 2022 02: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 salrashid123/270f3c68914db5aaa2e94095c846c744 to your computer and use it in GitHub Desktop.
Save salrashid123/270f3c68914db5aaa2e94095c846c744 to your computer and use it in GitHub Desktop.
Golang SignedURL with IAM API
package main
import (
"context"
"encoding/base64"
"fmt"
"io/ioutil"
"log"
"net/http"
"time"
"cloud.google.com/go/storage"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/iamcredentials/v1"
)
var ()
const ()
func main() {
ctx := context.Background()
// ****************************************
rootTokenSource, err := google.DefaultTokenSource(ctx, "https://www.googleapis.com/auth/iam")
if err != nil {
log.Fatal(err)
}
targetPrincipal := "oidc-federated@PROJECT_ID.iam.gserviceaccount.com"
bucketName := "mineral-minutia-820-cab1"
delegates := []string{}
object := "file1.txt"
expires := time.Now().Add(time.Minute * 10)
s, err := storage.SignedURL(bucketName, object, &storage.SignedURLOptions{
Scheme: storage.SigningSchemeV4,
GoogleAccessID: targetPrincipal,
SignBytes: func(b []byte) ([]byte, error) {
client := oauth2.NewClient(context.TODO(), rootTokenSource)
service, err := iamcredentials.New(client)
if err != nil {
return nil, fmt.Errorf("oauth2/google: Error creating IAMCredentials: %v", err)
}
signRequest := &iamcredentials.SignBlobRequest{
Payload: base64.StdEncoding.EncodeToString(b),
Delegates: delegates,
}
name := fmt.Sprintf("projects/-/serviceAccounts/%s", targetPrincipal)
at, err := service.Projects.ServiceAccounts.SignBlob(name, signRequest).Do()
if err != nil {
return nil, fmt.Errorf("oauth2/google: Error calling iamcredentials.SignBlob: %v", err)
}
sDec, err := base64.StdEncoding.DecodeString(at.SignedBlob)
if err != nil {
return nil, fmt.Errorf("oauth2/google: Error decoding iamcredentials.SignBlob response: %v", err)
}
return []byte(sDec), nil
},
Method: http.MethodGet,
Expires: expires,
})
if err != nil {
log.Fatal(err)
}
log.Println(s)
resp, err := http.Get(s)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
log.Println("SignedURL Response :\n", string(body))
if err != nil {
log.Fatal(err)
}
}
@salrashid123
Copy link
Author

  1. Additional permission required
"roles/iam.workloadIdentityUser"
| iam.serviceAccounts.get            |
| iam.serviceAccounts.getAccessToken |
| iam.serviceAccounts.getOpenIdToken |
| iam.serviceAccounts.list  

is missing signBlob() permissions.
which means you also need to add serviceAccountTokenCreator role to the service account

gcloud iam service-accounts add-iam-policy-binding oidc-federated@$PROJECT_ID.iam.gserviceaccount.com \
    --role roles/iam.serviceAccountTokenCreator \
    --member "principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/oidc-pool-run/subject/alice@domain.com"

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