func GenerateJWT()

in client/jwt/jwt.go [69:118]


func GenerateJWT(ctx context.Context, audience string) (string, error) {
	// First, check to see if the GOOGLE_APPLICATION_CREDENTIALS environment
	// variable has been set. If so, we can assume we are running on either
	// an on-prem environment (ie. not in GCE), or alternatively, we *are*
	// running in a GCE VM, but the user has chosen to override the default
	// service account with explicit credentials from another account. In
	// either case, we want to use this private key file to generate our JWT.
	if saKeyFile := os.Getenv(googleCredsEnvVar); saKeyFile != "" {
		// Read the service account file manually, as we need the email.
		sa, err := os.ReadFile(saKeyFile)
		if err != nil {
			return "", fmt.Errorf("failed to read service account file: %v", err)
		}

		conf, err := google.JWTConfigFromJSON(sa)
		if err != nil {
			return "", fmt.Errorf("could not parse service account JSON: %v", err)
		}

		// Request an OIDC token from IAM. Creating a new IAM credentials client
		// implicitly will look for the private key file specified in the
		// GOOGLE_APPLICATION_CREDENTIALS env var, so we don't need to pass
		// option.WithCredentials(saKeyFile) as an argument here.
		c, err := credentials.NewIamCredentialsClient(ctx)
		if err != nil {
			return "", fmt.Errorf("could not create a new IAM credentials client: %v", err)
		}
		defer c.Close()

		resp, err := c.GenerateIdToken(ctx, &iamcredspb.GenerateIdTokenRequest{
			Name:         serviceAccountPrefix + conf.Email,
			Audience:     audience,
			IncludeEmail: true,
		})

		if err != nil {
			return "", fmt.Errorf("error generating ID token: %v", err)
		}

		return resp.GetToken(), nil
	}

	// Otherwise, if we're not running in a GCE VM, we can't generate a signed
	// JWT from a service account, so return an error.
	if !metadata.OnGCE() {
		return "", fmt.Errorf("could not find GOOGLE_APPLICATION_CREDENTIALS and not running on GCE")
	}

	return instanceIdentityToken(audience)
}