问题
Context: I have just learn a trick to get (download) data from FireStore Dashboard. Obviouslly, it is much easier just open Google Dashboard on Browser and see with my eyes to own Google Dasboard. Nevertheless, for personal reasons, in my company the operators can't look at a third Dashboard. They only can see internal Dashboards. I am trying some workaround where I can get/download the same data used for fill in Dashboard and imported it to our internal solution based on Dynatrace/ELK.
For learning purposes, in order to download Google Dashboard data I followed:
1 - Get a ACCESS_TOKEN using gcloud
C:\Program Files (x86)\Google\Cloud SDK>gcloud auth application-default print-access-token
C:\Program Files (x86)\Google\Cloud SDK\google-cloud-sdk\bin\..\lib\third_party\google\auth\_default.py:69: UserWarning: Your application has authenticated using end user credentials from Google Cloud SDK. We recommend that most server applications use service accounts instead. If your application continues to use end user credentials from Cloud SDK, you might receive a "quota exceeded" or "API not enabled" error. For more information about service accounts, see https://cloud.google.com/docs/authentication/
warnings.warn(_CLOUD_SDK_CREDENTIALS_WARNING)
ya29. ... ACCESS-TOKEN ...7hu
2 - using the above ACCESS_TOKEN to get Dashboard data like:
curl --location --request GET 'https://monitoring.googleapis.com/v3/projects/firetestjimis/timeSeries?filter=metric.type%20%3D%20%22firestore.googleapis.com%2Fdocument%2Fread_count%22&interval.endTime=2020-05-07T15:01:23.045123456Z&interval.startTime=2020-05-05T15:01:23.045123456Z' --header 'Authorization: Bearer ya29...ACCESS-TOKEN 7hu'
Obviously this is just an example how to get how many conections satisfied the filter criteria. I can keep searching adjusting the API and filters according to Google Cloud Metrics and Google Cloud API v3
Other example of getting Dashboard metada this time from API version 1 is
curl --location --request GET 'https://monitoring.googleapis.com/v1/projects/firetestjimis/dashboards' --header 'Authorization: Bearer ya29... ACCESS-TOKEN ...7hu'
The warning when getting the ACCESS-TOKEN from gcloud encourage to see Authentication guidance and I did it. Well, it doens't explain how to fix this warning neither why "If your application continues to use end user credentials from Cloud SDK, you might receive a "quota exceeded" or "API not enabled" error". I can see my trick to get data from Dashboard is working but it seems I am relying on strange way to get a ACCESS-TOKEN.
So my straight question is: what is the appropriate steps to get manually an ACCESS-TOKEN and use it in curl/postman avoiding such warnning?
It seems to me that, based on this stackoverflow answer the root cause is "... This error message means you're using a User account, and not a service account..." So how can I fix it? Do I have to create a service account? If so, how? At the end of this accepted answer I read "... to use the true application default you can use gcloud auth application-default login..." And it is exactly how I am logging with gcloud: run gcloud auth application-default login, when open Google SingleSignOn I pick my email which is the the same user I registered in Firebase account. The answer also mentioned "... method to associate a specific service account is gcloud auth activate-service-account --key-file ...." I want give a try on it but which key-file is he/she talking about?
In case it is relevant, in my case I am only using FireStore under Firebase project (I am not using anything else other than FireStore).
*** EDITED after John's answer
We are moving soon this project to production.
1 - Our Mobile App will create money transfer by posting it to our internal microserve. Such post request will return a CustomToken generated from our internal NodeJs server.
2 - Our internal microservice will replicate such transfer to Firestore and update its state on Firestore accordingly.
3 - Instead of our Mobilie App poll or listen our internal microservice to get the status it will listen to Firestore for getting the status from respective document. In order to listen, it will use the CustomToken returned from post in step 1. Our company wants just take advantage of Real Time Database feature from Google Firestore for this project (reactive approach).
Do you see any consideration when compared what I am doing with your statement: "Google prefers in most cases that you authorize using a service account"?
The CustomToken is created internally with this NodeJs server and depending on uid extrated from antenticated user authentication/users from Google Firebase:
const admin = require('firebase-admin');
exports.serviceAccount = {
"type": "service_account",
"project_id": "firetestjimis",
"private_key_id": "ecfc6 ... fd05923",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIE .... 5EKvQ==\n-----END PRIVATE KEY-----\n",
"client_email": "firebase-adminsdk-fg6p9@firetestjimis.iam.gserviceaccount.com",
"client_id": "102422819688924138150",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-fg6p9%40firetestjimis.iam.gserviceaccount.com"
}
admin.initializeApp({
credential: admin.credential.cert(exports.serviceAccount)
});
var uid = "NS .... Ro2"; //copied from https://console.firebase.google.com/project/firetestjimis/authentication/users
var claim = {
control: true
};
admin.auth().createCustomToken(uid)
.then(function (customToken) {
console.log(customToken)
})
.catch(function (error) {
console.log("Error creating custom token:", error);
});
Our mobile (example in Angular but same idea for IOS and Android) has the SERVICE_ACCOUNT_JSON_FILE I downloaded like this:
environment.ts:
export const environment = {
production: false,
firebaseConfig: {
apiKey: "AIzaSy ... 3DCGihK3xs",
authDomain: "firetestjimis.firebaseapp.com",
databaseURL: "https://firetestjimis.firebaseio.com",
projectId: "firetestjimis",
storageBucket: "firetestjimis.appspot.com",
messagingSenderId: "795318872350",
appId: "1:7953 ... 32b26fb53dc810f"
}
};
app.component.ts
public transfers: Observable<any[]>;
transferCollectionRef: AngularFirestoreCollection<any>;
constructor(public auth: AngularFireAuth, public db: AngularFirestore) {
this.listenSingleTransferWithToken();
}
async listenSingleTransferWithToken() {
await this.auth.signInWithCustomToken("eyJh ### CUSTOMTOKEN GENERATED FROM INTERNAL NODEJS SERVER ABOVE ### CVg");
this.transferCollectionRef = this.db.collection<any>('transfer', ref => ref.where("id", "==", "1"));
this.transfers = this.transferCollectionRef.snapshotChanges().map(actions => {
return actions.map(action => {
const data = action.payload.doc.data();
const id = action.payload.doc.id;
return { id, ...data };
});
});
}
}
I understand that both CustomToken creation and its use from our Mobile is relying entirely on Service Account. Am I right? Did I miss some concept and I am using USER CREDENTIAL behind the scene and something that works properly in DEV environment will pop up some surprise when in production? Obviously for this question all comes from my free accoutn but in production it will be paid account but the code and steps will be exactly the same here.
回答1:
There are two types of credentials used by the CLI:
- User Credentials
- Service Accounts
Google prefers in most cases that you authorize using a service account. However, some services require user credentials (usually non-Google Cloud Platform services). Consult the documentation for each service that you use.
Execute the following command. This will show the credentials you are using:
gcloud auth list
To configure the CLI to use a service account, execute this command:
gcloud auth activate-service-account <SERVICE_ACCOUNT_EMAIL_ADDRESS> --key-file=<SERVICE_ACCOUNT_JSON_FILE>
I wrote an article that explains in more detail (and several additional articles on services accounts, authorization, etc.):
Google Cloud – Setting up Gcloud with Service Account Credentials
回答2:
So, the auth token is generated from your gcloud init
authorization, which is end-user credentials. That's why you're getting that warning. Because you've used your manually signed in credentials to generate the token.
The preferred way to auth is to use a service account (documentation here: https://cloud.google.com/iam/docs/service-accounts) for authentication. That documentation will also walk you through creating a service account. If you're using it to talk to Firestore, your service account will need appropriate Firestore role permissions. Not to confuse you, but the roles in IAM are for datastore
although they apply for Firestore.
This page: https://cloud.google.com/firestore/docs/security/iam lists out which roles/permissions your service account will need in order to do various things with Firestore.
Now, all that being said, the key-file it's talking about is the service account key that you can download when you create the service account. Easiest is to do it via the console in your GCP project, as when you're creating the service account, there's a handy button to create the key, and it downloads it to your local machine.
来源:https://stackoverflow.com/questions/61660600/cloud-sdk-credentials-warning-we-recommend-that-most-server-applications-use-ser