Created
August 4, 2020 23:05
-
-
Save salrashid123/575d761b1b4a28751173e49a95d773a3 to your computer and use it in GitHub Desktop.
basic GCP IAMCredentials `crypto.Signer()`
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 kms | |
import ( | |
"crypto" | |
"encoding/base64" | |
"io" | |
"sync" | |
"context" | |
"fmt" | |
"golang.org/x/oauth2" | |
"google.golang.org/api/iam/v1" | |
) | |
const () | |
var ( | |
refreshMutex = &sync.Mutex{} | |
rootTokenSource oauth2.TokenSource | |
serviceAccountName string | |
service *iam.Service | |
) | |
type IAM struct { | |
crypto.Signer | |
crypto.Decrypter | |
RootTokenSource oauth2.TokenSource | |
ServiceAccountName string | |
} | |
func NewIAMCrypto(conf *IAM) (IAM, error) { | |
if conf.RootTokenSource == nil || conf.ServiceAccountName == "" { | |
return IAM{}, fmt.Errorf("RootTokenSource cannot be null") | |
} | |
var err error | |
ctx := context.Background() | |
client := oauth2.NewClient(ctx, conf.RootTokenSource) | |
service, err = iam.New(client) | |
if err != nil { | |
return IAM{}, err | |
} | |
return *conf, nil | |
} | |
func (t IAM) Sign(_ io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) { | |
refreshMutex.Lock() | |
defer refreshMutex.Unlock() | |
name := fmt.Sprintf("projects/-/serviceAccounts/%s", t.ServiceAccountName) | |
signRequest := &iam.SignBlobRequest{ | |
BytesToSign: base64.StdEncoding.EncodeToString(digest), | |
} | |
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.Signature) | |
if err != nil { | |
return nil, fmt.Errorf("oauth2/google: Error calling iamcredentials.SignBlob: %v", err) | |
} | |
return sDec, err | |
} | |
Author
salrashid123
commented
Aug 4, 2020
Thank you for your sample!
I reached here from issue comment
However, this sample code does not work for me, so I made a new sample.
I hope this helps someone.
package main
import (
"context"
"io/ioutil"
"log"
"net/http"
"time"
"cloud.google.com/go/iam/credentials/apiv1"
"cloud.google.com/go/storage"
pb "google.golang.org/genproto/googleapis/iam/credentials/v1"
)
const (
project = "<PROJECT>"
bucket = "<BUCKET>"
object = "foo.txt"
serviceAccount = "<SERVICE_ACCOUNT>@<PROJECT>.iam.gserviceaccount.com"
scopeIAM = "https://www.googleapis.com/auth/iam"
)
func main() {
ctx := context.Background()
// prepare download file
gcs, err := storage.NewClient(ctx)
if err != nil {
log.Fatal(err)
}
obj := gcs.Bucket(bucket).Object(object)
w := obj.NewWriter(ctx)
if _, err := w.Write([]byte("hello, foo")); err != nil {
log.Fatal(err)
}
if err := w.Close(); err != nil {
log.Fatal(err)
}
// create signed url
s, err := storage.SignedURL(bucket, object, &storage.SignedURLOptions{
Scheme: storage.SigningSchemeV4,
GoogleAccessID: serviceAccount,
Method: "GET",
Expires: time.Now().Add(time.Minute * 1),
SignBytes: func(b []byte) ([]byte, error) {
c, err := credentials.NewIamCredentialsClient(context.Background())
if err != nil {
return nil, err
}
signRequest := &pb.SignBlobRequest{
Name: "projects/-/serviceAccounts/" + serviceAccount,
Payload: b,
}
res, err := c.SignBlob(ctx, signRequest)
if err != nil {
return nil, err
}
return res.GetSignedBlob(), nil
},
})
if err != nil {
log.Fatal(err)
}
log.Println("signed url:", s)
resp, err := http.Get(s)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
log.Println("SignedURL Response :\n", string(body))
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment