Is there a way to programmatically access the email of the currently used Service Account on a GCP instance when no GOOGLE_APPLICATION_CREDENTIALS is set? (ie. when using the default Service Account)
I've looked through the GCP documentation, but the only resource I found can't be used with the default Service Account when no GOOGLE_APPLICATION_CREDENTIALS is set. I know that it is possible to do so using gcloud (see this SO question or documentation), however these solutions aren't applicable when running on a ContainerOptimisedOS. I've spent a couple of weeks back and forth with the GCP support team, but they concluded with not being able to help me and redirected me to Stack Overflow for help.
The solution of John works great, on any language without any external library. However, it works only in Google Cloud environment, when a metadata server is deployed. You can't perform this test on your computer.
I propose just bellow a piece of Python code (with Google OAuth library, but it works in other languages that have this library) to ask the library the current credential. If the credential is a service account (from GOOGLE_APPLICATION_CREDENTIALS on your computer, the ADC (Application Default Credential) or from the metadata server), you have the email printed, else you have a warning message because you use your user account credential:
import google.auth
credentials, project_id = google.auth.default()
if hasattr(credentials, "service_account_email"):
print(credentials.service_account_email)
else:
print("WARNING: no service account credential. User account credential?")
Note that if the default service account is used this method will print default instead of the entire email address.
The Go version:
ctx := context.Background()
credential,err := google.FindDefaultCredentials(ctx)
content := map[string]interface{}{}
json.Unmarshal(credential.JSON, &content)
if content["client_email"] != nil {
fmt.Println(content["client_email"])
} else {
fmt.Println("WARNING: no service account credential. User account credential?")
}
Just adding to the accepted answer. As stated in the answer this seems to return "default":
import google.auth
credentials, project_id = google.auth.default()
# returns "default"
print(credentials.service_account_email)
I found to get the email name of the GSA currently active (via the metadata api) I had to manually refresh first:
import google.auth
import google.auth.transport.requests
credentials, project_id = google.auth.default()
request = google.auth.transport.requests.Request()
credentials.refresh(request=request)
# returns "[email protected]"
print(credentials.service_account_email)
I'm using workload ID. I think maybe there is a race condition and I'm trying to read the service_account_email property before the creds get initialized for the first time when the pod starts.
The _retrieve_info() function is called when refresh() is called and it appears this is the function that grabs the email name.
If I had my script sleep for a few seconds on start up, I wonder if service_account_email would eventually be populated with the email name of the GSA.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With