I am building a multilingual SAAS website builder in Golang which is run per client. Each client can have their own website and can translate their website in the desired language.
Since the feature is per client, so I collected an API key from client, which I used to translate their site content.
Here is the code,
V2
package main
import (
"context"
"fmt"
"cloud.google.com/go/translate"
"google.golang.org/api/option"
)
func main() {
translationStrings := []string{"hello"}
ctx := context.Background()
opts := option.WithAPIKey(APIKEY)
c, err := translate.NewClient(ctx, opts)
if err != nil {
fmt.Println(err)
}
defer c.Close()
resp, err := c.Translate(ctx, translationStrings, language.French,
&translate.Options{
Source: language.English,
Format: translate.Text,
})
if err != nil {
fmt.Println(err)
}
fmt.Println(resp)
}
V3
translate "cloud.google.com/go/translate/apiv3"
translatepb "google.golang.org/genproto/googleapis/cloud/translate/v3"
c, err := translate.NewTranslationClient(ctx, opts)
if err != nil {
fmt.Println(err)
}
defer c.Close()
req := &translatepb.TranslateTextRequest{
Contents: translationStrings,
TargetLanguageCode: "sr-Latn",
}
resp, err := c.TranslateText(ctx, req)
The code with V2 works well but the same code with V3 does not work. It gives error:
API keys are not supported for gRPC APIs. Remove the WithAPIKey option from your client-creating call.
As stated in the error, it is asking me to remove WithAPIKey options. But if I remove this then how will I use the api key for each client.
I have chosen to work with V3 apis because the will be translated as a whole so it will be a large request. I have read in the docs that V3 api can work in batches.
So my questions are:
how can I use per client api key structure with api V3?
Is it okay to go with the api V2 for the purpose as stated above?
Cloud Translation API v3 does not currently support API keys. It is recommended that you create a service account for Cloud Translation API v3 requests. For information on creating a service account, see Creating and managing service accounts. Your service account must be added to one of the IAM roles added for Cloud Translation API v3.
Related
I am able to create a new spreadsheet with the gsheets client library, and my next step is to add editors to that newly created sheet so that the sheet can be accessed by the users of the application
Here is the code for creating the sheet:
ctx := context.Background()
srv, err := gsheets.NewService(ctx)
if err != nil {
log.Printf("Unable to retrieve Sheets client: %v", err)
}
sp := &gsheets.Spreadsheet{
Properties: &gsheets.SpreadsheetProperties{
Title: groupName,
},
}
spreadsheet, err := srv.Spreadsheets.Create(sp).Do()
if err != nil {
return nil, err
}
I have searched through the golang client library docs and the REST API docs, and I am unable to find anything related to adding collaborators
I was expecting there to be some request object that allows me to add a collaborator using their email and role:
req := gsheets.Request{
AddCollaborator: &gsheets.AddCollaboratorRequest{
Email: "person#gmail.com",
Role: "editor",
},
}
busr := &gsheets.BatchUpdateSpreadsheetRequest{
Requests: []*gsheets.Request{&req},
}
res, err := srv.Spreadsheets.BatchUpdate(spreadsheetId, busr).Do()
or at the very least I was expecting there to be an API endpoint where I can achieve the same result
I am also curious if there is a way to create this new spreadsheet as read only to the public? This would at least allow me to continue developing
It is possible to add editors with the google.golang.org/api/sheets/v4 library.
You can simply create a spreadsheet with:
func (r *SpreadsheetsService) Create(spreadsheet *Spreadsheet) *SpreadsheetsCreateCall
and add editors with Editor type:
type Editors struct {
...
// Users: The email addresses of users with edit access to the protected
// range.
Users []string `json:"users,omitempty"`
...
}
Check library docs for more details.
Im using the following code which works as expected, I use from the cli gcloud auth application-default login and enter my credentials and I was able to run the code successfully from my macbook.
Now I need to run this code in my CI and we need to use different approach , what should be the approach to get the client_secret
and client_id or service account / some ENV variable, what is the way for doing it via GO code?
import "google.golang.org/api/compute/v1"
project := "my-project"
region := "my-region"
ctx := context.Background()
c, err := google.DefaultClient(ctx, compute.CloudPlatformScope)
if err != nil {
log.Fatal(err)
}
computeService, err := compute.New(c)
if err != nil {
log.Fatal(err)
}
req := computeService.Routers.List(project, region)
if err := req.Pages(ctx, func(page *compute.RouterList) error {
for _, router := range page.Items {
// process each `router` resource:
fmt.Printf("%#v\n", router)
// NAT Gateways are found in router.nats
}
return nil
}); err != nil {
log.Fatal(err)
}
Since you're using Jenkins you probably want to start with how to create a service account. It guides you on creating a service account and exporting a key to be set as a var in another CI/CD system.
Then refer to the docs from the client library on how to create a new client with source credential.
e.g.
client, err := storage.NewClient(ctx, option.WithCredentialsFile("path/to/keyfile.json"))
If you provided no source, it would attempt to read the credentials locally and act as the service account running the operation (not applicable in your use case).
Many CIs support the export of specific env vars. Or your script / conf can do it too.
But if you want to run in a CI why you need such configuration? Integration tests?
Some services can be used locally for unit/smoke testing. Like pubsub, there is a way to run a fake/local pubsub to perform some tests.
Or perhaps I did not understand your question, in this case can you provide an example?
I'm using this example provided under cloud functions to make a GET request to another GCP API:
import (
"context"
"fmt"
"io"
"google.golang.org/api/idtoken"
)
func makeGetRequest(w io.Writer, targetURL string) error {
ctx := context.Background()
client, err := idtoken.NewClient(ctx, targetURL)
if err != nil {
return fmt.Errorf("idtoken.NewClient: %v", err)
}
resp, err := client.Get(targetURL)
if err != nil {
return fmt.Errorf("client.Get: %v", err)
}
defer resp.Body.Close()
if _, err := io.Copy(w, resp.Body); err != nil {
return fmt.Errorf("io.Copy: %v", err)
}
return nil
}
but when I log the request sent I don't see any authorization header and I get the following error:
"Request
had invalid authentication credentials. Expected OAuth 2 access token, login cookie
or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.\"
I have given serviceAccountTokenCreator and the target GCP API admin permissions to the service account that's used to create the cloud function.
Am I misunderstanding what the documentation is saying? It seems like the authorization header should be automatically added.
It might be easier for you to not build the request from scratch and use Client Libraries instead. It provides idiomatic, generated or hand-written code in each language, making the Cloud API simple and intuitive to use. It also handles authentication for you.
From what you're following, the client automatically adds an "Authorization" header so that shouldn't be the problem. You're also trying to follow an example that generates an Identity Token, because calling a Cloud Function endpoint that has authentication requires an Identity token. This is different on your use case, because calling GCP APIs require an OAuth 2 access token. This link explains the difference between the two.
There are ways to generate an access token programmatically such as getting them from the metadata server as I did in my other answer (it's in Python but you can also do it in Golang). However, I suggest learning more on how Client Libraries work and test it for yourself. There are many examples shown on GitHub to get you started.
I'd like to create Signed URLs to Google Cloud Storage resources from an app deployed using CloudRun.
I set up CloudRun with a custom Service Account with the GCS role following this guide.
My intent was to use V4 Signing to create Signed URLs from CloudRun. There is a guide for this use-case where a file service_account.json is used to generate JWT config. This works for me on localhost when I download the file from google's IAM. I'd like to avoid having this file committed in the repository use the one that I provided in CloudRun UI.
I was hoping that CloudRun injects this service account file to the app container and makes it accessible in GOOGLE_APPLICATION_CREDENTIALS variable but that's not the case.
Do you have a recommendation on how to do this? Thank you.
As you say, Golang Storage Client Libraries require a service account json file to sign urls.
There is currently a feature request open in GitHub for this but you should be able to work this around with this sample that I found here:
import (
"context"
"fmt"
"time"
"cloud.google.com/go/storage"
"cloud.google.com/go/iam/credentials/apiv1"
credentialspb "google.golang.org/genproto/googleapis/iam/credentials/v1"
)
const (
bucketName = "bucket-name"
objectName = "object"
serviceAccount = "[PROJECTNUMBER]-compute#developer.gserviceaccount.com"
)
func main() {
ctx := context.Background()
c, err := credentials.NewIamCredentialsClient(ctx)
if err != nil {
panic(err)
}
opts := &storage.SignedURLOptions{
Method: "GET",
GoogleAccessID: serviceAccount,
SignBytes: func(b []byte) ([]byte, error) {
req := &credentialspb.SignBlobRequest{
Payload: b,
Name: serviceAccount,
}
resp, err := c.SignBlob(ctx, req)
if err != nil {
panic(err)
}
return resp.SignedBlob, err
},
Expires: time.Now().Add(15*time.Minute),
}
u, err := storage.SignedURL(bucketName, objectName, opts)
if err != nil {
panic(err)
}
fmt.Printf("\"%v\"", u)
}
Cloud Run (and other compute platforms) does not inject a service account key file. Instead, they make access_tokens available on the instance metadata service. You can then exchange this access token with a JWT.
However, often times, Google’s client libraries and gcloud works out of the box on GCP’s compute platforms without explicitly needing to authenticate. So if you use the instructions on the page you linked (gcloud or code samples) it should be working out-of-the-box.
Is there any way to create a user in Firebase using Userame, Email and Password with Golang. A user can be created with Javascript using createUserWithEmailAndPassword(email, password) But I need the same with Golang. Is there a package or function available? I am using firego to connect with Firebase.
Recently Google added Go Lang to their list of programming languages that are supported by Firebase Authentication using Firebase Admin SDK.
To create a user:
params := (&auth.UserToCreate{}).
Email("user#example.com").
EmailVerified(false).
PhoneNumber("+1234567890").
Password("secretPassword").
DisplayName("Donald Drump").
PhotoURL("http://www.example.com/12345678/photo.png").
Disabled(false)
u, err := client.CreateUser(context.Background(), params)
if err != nil {
log.Fatalf("error creating user: %v\n", err)
}
log.Printf("Successfully created user: %v\n", u)
if you want to create a user with your own user ID and don't want an automated generated ID by Firebase then:
params := (&auth.UserToCreate{}).
UID(uid).
Email("user#example.com").
PhoneNumber("+1234567890")
u, err := client.CreateUser(context.Background(), params)
if err != nil {
log.Fatalf("error creating user: %v\n", err)
}
log.Printf("User created successfully : %v\n", u)
to update a user:
params := (&auth.UserToUpdate{}).
Email("user#example.com").
EmailVerified(true).
PhoneNumber("+1234567890").
Password("newPassword").
DisplayName("Donald Drump").
PhotoURL("http://www.example.com/12345678/photo.png").
Disabled(true)
u, err := client.UpdateUser(context.Background(), uid, params)
if err != nil {
log.Fatalf("error updating user: %v\n", err)
}
log.Printf("Successfully updated user: %v\n", u)
Firebase has added an Admin SDK for Go. See Mujtaba's answer for more information: https://stackoverflow.com/a/47889860
Previous answer:
There is no Firebase SDK for Go. But certain parts of Firebase have a REST API that allows you to use those features from almost any platform/technology. The Firebase Database is one of those features and the Firego library is a wrapper around the REST API of the Firebase Database for Go developers.
Unfortunately there is no REST API for creating users in Firebase Authentication. So it won't be possible to create users through Firego or through a public REST API from your Go code.
The simplest solution would be to create a REST endpoint on a app server you control, where you then use the Firebase Admin SDK to create the user.