While trying to generate Let’s Encrypt SSL certificates with lego and gcloud DNS, I encountered an error that would not allow me to obtain a certificate.
The error encountered was:
[example.com] Could not obtain certificates
Error presenting token: GoogleCloud API call failed: Get https://www.googleapis.com/dns/v1/projects/example-project/managedZones?alt=json&dnsName=example.com.: oauth2: cannot fetch token: 400 Bad Request
Response: {
"error" : "invalid_grant"
}
Having never encountered this error before, the first thing I tried was to revoke my credentials with command gcloud auth revoke
and re-authenticate with command gcloud auth login
, but it didn’t work.
Google searching didn’t reveal much. All I found were the following two posts, but the fixes either didn’t work or apply to me:
- Google OAuth “invalid_grant” nightmare — and how to fix it
- invalid_grant trying to get oAuth token from google
Next, I thought I had corrupted keys or tokens, so I created a backup of my current gcloud directory (~/.config/gcloud), deleted the current gcloud directory, and let the gcloud
command create a new one.
After reauthenticating with command gcloud auth login
, I ran the lego
command from above again but encountered the following error:
Unable to get Google Cloud client: google: could not find default credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.
Because I had created a new gcloud directory, I didn’t have any application default credentials; this was confirmed by running command gcloud auth application-default print-access-token
. Before deleting the gcloud directory, I had application default credentials set, but the token must have been invalidated causing the invalid_grant error from above.
After reading the following description - obtained by running command gcloud auth application-default
- why I was encountering this issue started making more sense:
Application Default Credentials provide a simple way to get authorization credentials for use in calling Google APIs. These commands assist in managing the active credentials on your machine that are used for testing purposes during local application development. These credentials are strictly used by Google client libraries in your own application. They are not used for any API calls made by the
gcloud
CLI, nor do they have any interaction with the credentials acquired bygcloud auth login
. For more information on ADC and how they work, see: https://developers.google.com/identity/protocols/application-default- credentials
The lego
command does not call the gcloud
command directly; it uses the Google Cloud APIs directly which requires an application default credential. Any program that uses the Google Cloud APIs directly is going to require an application default credential. This is a separate form of authentication than what gcloud auth login
creates for you.
Finally, I more than likely did not need to create a new gcloud directory, I could have simply run the following two commands to get a new application default credential token:
gcloud auth application-default revoke
gcloud auth application-default login
After running those commands, I was able to run the lego
command from above to generate the Let’s Encrypt SSL certificates.