Reputation: 729
I've added some secrets to the Secret Manager but I get the following error trying to access them at runtime:
rpc error: code = Unauthenticated desc = transport: compute: Received 500 `Could not fetch URI /computeMetadata/v1/instance/service-accounts/default/token?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform
This is an old app I'm setting up again so I must have missed something in the permissions. I'm accessing the keys via the full path with the project id and the key name.
I've run gcloud app describe
and verified that the serviceAccount
listed there has the Owner
Role. I've also added Owner
to the App engine default service account. I've tried the specific Secret Manager Accessor role as well.
Update: The service matches the golang example in the docs for accessing a secret. It's using the standard google libraries for create a client and requests. I am not explicitly configuring authentication so the app should be using the service account as described here.
The path for the secret looks valid:
projects/<my-project-id>/secrets/MY_SECRET/versions/latest
The error message suggests it's missing a cloud-platform scope but I don't see any specific configuration for this since it's Google App Engine.
Update 2: I've pushed a repo that recreates this. It uses the sample code from google for accessing a secret and fails with the same error about the cloud-platform scope.
Upvotes: 1
Views: 8553
Reputation: 1218
For troubleshooting your app, I would suggest to do the following:
To be sure that the code you deploy to App Engine is running with the desired account, I suggest Passing credentials using code and explicitly point to your service account file in code.
./project-folder
├── test.go
├── service-account-credentials.json
├── ...
With a new project folder, create a service account key and save in the folder.
Use the following code to test that your service account has the proper permissions, to discard that the problem is App Engine not using the proper account. You can check your App Engine logs in case something goes wrong.
package main
import (
"context"
"fmt"
"log"
"net/http"
"os"
secretmanager "cloud.google.com/go/secretmanager/apiv1"
"google.golang.org/api/option"
secretmanagerpb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"
"google.golang.org/grpc/status"
)
// Your Project ID
const projectId = "project-id"
// Name of your secret
const secret = "secret"
func main() {
// Path to your secret
// The version can be a version number as a string (e.g. "5") or an
// alias (e.g. "latest").
name := fmt.Sprintf("projects/%s/secrets/%s/versions/latest", projectId, secret)
ctx := context.Background()
// Explicitly reads credentials from the specified path.
// Create the client.
client, err := secretmanager.NewClient(ctx,
option.WithCredentialsFile("service-account-key.json"))
if err != nil {
log.Fatal("Failed to create secretmanager client\n")
if s, ok := status.FromError(err); ok {
log.Println(s.Message())
for _, d := range s.Proto().Details {
log.Println(d)
}
}
}
defer client.Close()
// Build the request.
req := &secretmanagerpb.AccessSecretVersionRequest{
Name: name,
}
// accessSecretVersion accesses the payload for the given secret version if one exists.
// Call the API.
result, err := client.AccessSecretVersion(ctx, req)
if err != nil {
log.Fatal("Failed to access secret version\n")
if s, ok := status.FromError(err); ok {
log.Println(s.Message())
for _, d := range s.Proto().Details {
log.Println(d)
}
}
}
// WARNING: Do not print the secret in a production environment - this snippet
// is showing how to access the secret material.
log.Printf("Plaintext: %s\n", string(result.Payload.Data))
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, `<h1>For testing purposes only.</h1>
<h2>Do not use in production enviroments</h2>
<p>Your secret is shown on Logs.<p>`)
})
port := os.Getenv("PORT")
fmt.Printf("Starting server at port %s\n", port)
if err := http.ListenAndServe(":"+port, nil); err != nil {
log.Fatal(err)
}
}
As mentioned, your service account must be using the Owner
role that grants permissions to the Secret Manager in order to access to the secret in Secret Manager.
See also
Upvotes: 1