Path: blob/main/components/gitpod-cli/cmd/idp-token.go
2498 views
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.1// Licensed under the GNU Affero General Public License (AGPL).2// See License.AGPL.txt in the project root for license information.34package cmd56import (7"context"8"encoding/json"9"fmt"10"time"1112connect "github.com/bufbuild/connect-go"13"github.com/gitpod-io/gitpod/common-go/util"14"github.com/gitpod-io/gitpod/components/public-api/go/client"15v1 "github.com/gitpod-io/gitpod/components/public-api/go/experimental/v1"16"github.com/gitpod-io/gitpod/gitpod-cli/pkg/gitpod"17supervisor "github.com/gitpod-io/gitpod/supervisor/api"18"github.com/golang-jwt/jwt/v5"19"github.com/spf13/cobra"20"golang.org/x/xerrors"21"google.golang.org/grpc"22"google.golang.org/grpc/credentials/insecure"23)2425var idpTokenOpts struct {26Audience []string27Decode bool28Scope string29}3031var idpTokenCmd = &cobra.Command{32Use: "token",33Short: "Requests an ID token for this workspace",34RunE: func(cmd *cobra.Command, args []string) (err error) {35cmd.SilenceUsage = true3637ctx, cancel := context.WithTimeout(cmd.Context(), 5*time.Second)38defer cancel()3940tkn, err := idpToken(ctx, idpTokenOpts.Audience, idpTokenOpts.Scope)4142token, _, err := jwt.NewParser().ParseUnverified(tkn, jwt.MapClaims{})43if err != nil {44return err45}4647// If the user wants to decode the token, then do so.48if idpTokenOpts.Decode {4950output := map[string]interface{}{51"Header": token.Header,52"Payload": token.Claims,53}5455// The header and payload are then marshalled into a map and printed to the screen.56outputPretty, err := json.MarshalIndent(output, "", " ")57if err != nil {58return xerrors.Errorf("Failed to marshal output: %w", err)59}6061fmt.Printf("%s\n", outputPretty)62return nil63}64fmt.Println(tkn)65return nil66},67}6869func idpToken(ctx context.Context, audience []string, scope string) (idToken string, err error) {70wsInfo, err := gitpod.GetWSInfo(ctx)71if err != nil {72return "", err73}74supervisorConn, err := grpc.Dial(util.GetSupervisorAddress(), grpc.WithTransportCredentials(insecure.NewCredentials()))75if err != nil {76return "", xerrors.Errorf("failed connecting to supervisor: %w", err)77}78defer supervisorConn.Close()79clientToken, err := supervisor.NewTokenServiceClient(supervisorConn).GetToken(ctx, &supervisor.GetTokenRequest{80Host: wsInfo.GitpodApi.Host,81Kind: "gitpod",82Scope: []string{83"function:getWorkspace",84},85})86if err != nil {87return "", xerrors.Errorf("failed getting token from supervisor: %w", err)88}8990c, err := client.New(client.WithCredentials(clientToken.Token), client.WithURL("https://api."+wsInfo.GitpodApi.Host))91if err != nil {92return "", err93}94tkn, err := c.IdentityProvider.GetIDToken(ctx, &connect.Request[v1.GetIDTokenRequest]{95Msg: &v1.GetIDTokenRequest{96Audience: audience,97WorkspaceId: wsInfo.WorkspaceId,98Scope: scope,99},100})101if err != nil {102return "", err103}104return tkn.Msg.Token, nil105}106107func init() {108idpCmd.AddCommand(idpTokenCmd)109110idpTokenCmd.Flags().StringArrayVar(&idpTokenOpts.Audience, "audience", nil, "audience of the ID token")111_ = idpTokenCmd.MarkFlagRequired("audience")112113idpTokenCmd.Flags().BoolVar(&idpTokenOpts.Decode, "decode", false, "decode token to JSON")114idpTokenCmd.Flags().StringVar(&idpTokenOpts.Scope, "scope", "", "scopes string of the ID token")115}116117118