Unable to create a custom domain using Firebase Hosting API - firebase

I'm trying to automate custom domain creation process in Firebase Hosting, I am using Go library, but it doesn't work, I am also happy to know about plain REST alternative. I always get this error:
googleapi: Error 400: Domain test1.example.com not associated with
project, failedPrecondition exit status 1
firebase, _ := firebasehosting.NewService(context.Background())
domain := &firebasehosting.Domain{
DomainName: "test1.example.com",
Site: "dashboard-v1-staging",
}
createCall := firebase.Projects.Sites.Domains.Create("projects/ID/sites/ID", domain)
_, err = createCall.Do()
if err != nil && !googleapi.IsNotModified(err) {
log.Println(err)
os.Exit(1)
}

I found out that API can't do that yet, and Firebase team is working on that. It was confirmed in the ticket I submitted on Github - https://github.com/googleapis/google-api-go-client/issues/1798

Related

Firebase Auth Emulator - Golang: Project not found

Recently I started testing my go server, which uses firebase admin sdk, with firebase local emulator suite. It works perfectly with firestore, but with the authentication not so much.
I tried many different approaches, including firebase demo project, my own demo project, and a simple test project. Nothing of those did the job; I kept receive the same error message, project not found.
Firebase Emulator
I use the firebase admin SDK, and I followed the insructions in the
official firebase article.
To configure the emulator, I ran firebase init and firebase init emulators in terminal. Those resulted in the files in the next section. Then the emulator starts with the command firebase emulators:start, and I added --project test to set the project ID.
Simplified Code
firebase.json
{
"emulators": {
"auth": {
"port": 9099
}
}
}
Simple JSON which describes the port for auth service.
.firebaserc
{}
This is empty because it doesn't have any project set, but I also tried adding projects here. Anyway, the project ID is set to "test" in both terminals, the one that runs the emulator, and the one that runs the golang app.
main.go
package main
import (
"context"
firebase "firebase.google.com/go"
"firebase.google.com/go/auth"
)
func main() {
ctx := context.Background()
config := &firebase.Config{ProjectID: "test"}
app, _ := firebase.NewApp(ctx, config)
Auth, _ := app.Auth(ctx)
params := (&auth.UserToCreate{}).
DisplayName("Some Name").
Email("example#gmail.com").
Password("password")
_, err := Auth.CreateUser(ctx, params)
if err != nil {
panic(err)
}
}
On the final line it panics with error status 400 Bad Request, and message PROJECT_NOT_FOUND. It looks like the admin SDK is looking at a public project with project ID "test", and I'm trying to emulate a local project.
Firestore emulator works, Auth does not.
I haven't found a single solution for this in golang. In node.js admin SDK the local auth emulator works, but I need the golang admin SDK.
How can I tell the go admin SDK for firebase auth emulator to look for a local project?

Using Google Firebase Golang libraries (e.g. IAP and Firestore) for a non-admin client application

Brief description
Hi everyone,
I am working with Golang, developing a software to run locally at home but also synchronize with some cloud data (individually secured per user login). For that, I decided to use Google Cloud Service - Firebase (IAP, Hosting, Functions, and Firestore). Let me tell you, I am loving to develop and learn about these.
However, here comes the problem: I get really confused with the Golang tools (libraries) provided by Google to work on their service. They seem to have well-defined Golang libraries to work with their services IF your code is running in a trusted machine since you have to export credentials to it.
In my case, the software I am developing will run on the client machine and so I need a client login to IAP, etc.
Can anyone help me with that?
Issue
none of the tool available seem to be specific for Golang client (not-admin)
Google provides many, MANY repositories, and links to different tools that seem to do similar things, which one of them is for Admin usage, which one uses their RPC server, which one could I use for my client?
cloud.google.com/go/
firebase.google.com/go
https://github.com/googleapis/google-cloud-go
google.golang.org/api/ (Deprecated, but still referenced in their documentation)
Google has very similar names for different versions of the same things;
Documentation does not seem to be clear enough to me, and if they have a specific library or not for my case.
What I achieved
Using the REST API I managed to get the tokenID (login) with one user account (created inside my IAP project);
With its tokenID, I managed to use the REST API to retrieve some document that he has access;
With the following code, I manage to use one of the Golang libraries (supposedly for admin credentials) to retrieve the same documents using a private IAP user account of my project.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
"golang.org/x/oauth2"
"google.golang.org/api/option"
)
func main() {
ctx := context.Background()
token := oauth2.Token{
AccessToken: "TOKEN_ID-FROM-IAP",
TokenType: "Bearer",
RefreshToken: "REFRESH_TOKEN-from-IAP",
}
oauthClient := &oauth2.Config{}
tSource := oauthClient.TokenSource(ctx, &token)
client, err := firestore.NewClient(ctx, "ProjectID", option.WithTokenSource(tSource))
if err != nil {
// TODO: Handle error.
}
defer client.Close()
iter := client.Doc("docPath").Snapshots(ctx)
defer iter.Stop()
for {
docsnap, err := iter.Next()
if err != nil {
// TODO: Handle error.
}
dataMap := docsnap.Data()
fmt.Println(dataMap)
}
}
Final questions
From the perspective of a non-admin client account of a private Firebase project:
Can anyone explain/clarify these many libraries?
I used oauth2 with the IAP token (acquired with the REST API), will this package work fine from now on?
Can I use oauth2 package to do more with IAP service? Like, renew the token, make login?
I appreciate thoughts and suggestions,
Thank you in advance!

Using Firebase for notifications, getting `app instance has been unregistered`

Trying to use Firebase for cross-platform mobile notifications. The client code to get a device token seems to work, as we can send notifications from the Firebase web console. But I cannot figure out how to send notifications from our server. We get the error: app instance has been unregistered; code: registration-token-not-registered; details: Requested entity was not found when calling messagingClient.Send in the following Go code snippet:
ctx := r.Context()
opt := option.WithCredentialsFile("serviceAccountKey.json")
app, err := firebase.NewApp(context.Background(), nil, opt)
if err != nil {
return err
}
// Obtain a messaging.Client from the App.
messagingClient, err := app.Messaging(ctx)
if err != nil {
return err
}
// See documentation on defining a message payload.
message := &messaging.Message{
Notification: &messaging.Notification{
Title: "Notification title",
Body: "Notification body",
},
Token: myDeviceToken,
}
// Send a message to the device corresponding to the provided
// registration token.
response, err := messagingClient.Send(ctx, message)
if err != nil {
return err
}
The credentials file that we're using is from the Firebase console, under Settings, Service Accounts, Firebase Admin SDK.
According to the documentation for FCM error codes, registration-token-not-registered means:
The provided registration token is not registered. A previously valid
registration token can be unregistered for a variety of reasons,
including:
The client app unregistered itself from FCM.
The client app was automatically unregistered. This can happen if the user uninstalls the application or, on iOS, if the APNS Feedback
Service reported the APNS token as invalid.
The registration token expired. For example, Google might decide to refresh registration tokens or the APNS token may have expired for iOS
devices.
The client app was updated, but the new version is not configured to receive messages.
For all these cases, remove this registration token and stop using it
to send messages.
Given that there are several possibilities here, it's not really possible for us to say which one it is. If you need assistance troubleshooting with FCM, please contact Firebase support directly with exact steps anyone can take to reproduce the issue.

Firebase Admin Go SDK getting x509 certificate error ONLY when running inside Kubernetes

I'm currently working on a project using the Firebase Admin Go SDK to handle auth and to use the real time database. The project works correctly when I run it locally (by just running go run main.go). When I run it in Minikube via a docker image (or GKE, I've tested both) I get this error whenever I try to make any Firestore calls:
transport: authentication handshake failed: x509: certificate signed by unknown authority
Here is the code I'm using on the server to make the call to the DB:
// Initialize the app
opt := option.WithCredentialsFile("./serviceAccountKey.json")
app, err := firebase.NewApp(context.Background(), nil, opt)
// This is the first call I attempt to make, and where the error is thrown
// Create the client
client, err := app.Firestore(context.Background())
iter := client.Collection("remoteModels").Documents(context.Background())
snaps, err := iter.GetAll()
if err != nil {
logger.Log.Warn("Error getting all remoteModels")
fmt.Println(err)
return err
}
And here is my Dockerfile that adds the service account key Firebase provided me from the console:
FROM scratch
ADD main /
ADD serviceAccountKey.json /
EXPOSE 9090
ENTRYPOINT ["/main", "-grpc-port=9090", "-http-port=9089", "-env=prod"]
I can't find anything in the documentation about running in Kubernetes.
Is there anything I need to do to be able to connect to Firestore from Kubernetes?
If you are using alpine based images try running apk add ca-certificates it looks like a tls error.
Install ca certificates, it should resolve the issue

Stackdriver logging not showing up for GKE

I appear to be missing some configuration somewhere but have no idea where.
My app (golang) is using stackdriver logging. When I run locally it works fine and my log messages show up in Stackdriver. When I run in GKE then my custom logger messages do not show up.
Any standard out messages (fmt.println()) will show up in stack driver. They just wont' ahve proper severity and would rather us the logging API. What could I have misconfigured in my GKE instance to make google logging not show up?
Sorry for the vague post but I don't have much to go on, not getting any errors.
Here is my code for sending messages if it helps.
func logMessage(message string, transactionID string, severity logging.Severity) {
ctx := context.Background()
// Creates a client.
client, err := logging.NewClient(ctx, loggingData.ProjectID)
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
// Selects the log to write to.
logger := client.Logger(loggingData.LogName)
logger.Log(logging.Entry{Payload: message, InsertID: transactionID, Severity: severity})
// Closes the client and flushes the buffer to the Stackdriver Logging
// service.
if err := client.Close(); err != nil {
log.Panicln("Failed to close client: \n", err.Error())
return
}
return
}
Update:
I got my SSH working into the Node (VM Instance) and confirmed that it looks like FluentD is working and picking up changes. I opened the log files and only saw things from fmt.Println and nothing from the golang cloud Logger.
Maybe I am not understanding how Google Stackdriver Logging (https://godoc.org/cloud.google.com/go/logging) is supposed to work? Clearly I am missing something and just not sure what yet.
Thanks
On GKE, fluentd agent is used and it's included in the VM image (node).
His role is to watch changes to Docker log files that live in the directory /var/lib/docker/containers/ and are symbolically linked to from the /var/log/containers directory using names that capture the pod name and container name. These logs are then submitted to Google Cloud Logging which assumes the installation of the cloud-logging plug-in.
You can customize your agent configuration for Streaming logs from additional inputs such as Streaming unstructured (text) or structured (JSON) logs via log files.
By default fluentd extract local_resource_id from tag for 'k8s_container' monitored:
The resource. The format is:
'k8s_container.<namespace_name>.<pod_name>.<container_name>'.
The fluentd agent rename the field 'log' to a more generic field 'message'. This way the fluent-plugin-google-cloud knows to flatten the field as textPayload instead of jsonPayload after extracting 'time', 'severity' and 'stream' from the record.
If 'severity' is not set, assume stderr is ERROR and stdout is INFO.
The agent can be enabled when creating the cluster, then the default fluentd pod will created.
You can as well perform a manual installation of stackdriver-logging-agent in GKE (fluentd).
First I will suggest you to find if you have an agent running.
To do, SSH to your node and check if the agent is running, run the below command line
ps ax | grep fluentd
Output example:
2284 ? Sl 0:00 /opt/google-fluentd/embedded/bin/ruby /usr/sbin/google-fluentd [...]
2287 ? Sl 42:44 /opt/google-fluentd/embedded/bin/ruby /usr/sbin/google-fluentd [...]
Do a test by running the below command line :
logger "Some test message"
Check stackdriver logging for your test message
I had similar issue with golang app running in Cloud Run
Was able to find stackdriver logs in Logs Viewer web UI by filter resource.type = "project"

Resources