Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/gitpod-cli/cmd/idp-token.go
2498 views
1
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package cmd
6
7
import (
8
"context"
9
"encoding/json"
10
"fmt"
11
"time"
12
13
connect "github.com/bufbuild/connect-go"
14
"github.com/gitpod-io/gitpod/common-go/util"
15
"github.com/gitpod-io/gitpod/components/public-api/go/client"
16
v1 "github.com/gitpod-io/gitpod/components/public-api/go/experimental/v1"
17
"github.com/gitpod-io/gitpod/gitpod-cli/pkg/gitpod"
18
supervisor "github.com/gitpod-io/gitpod/supervisor/api"
19
"github.com/golang-jwt/jwt/v5"
20
"github.com/spf13/cobra"
21
"golang.org/x/xerrors"
22
"google.golang.org/grpc"
23
"google.golang.org/grpc/credentials/insecure"
24
)
25
26
var idpTokenOpts struct {
27
Audience []string
28
Decode bool
29
Scope string
30
}
31
32
var idpTokenCmd = &cobra.Command{
33
Use: "token",
34
Short: "Requests an ID token for this workspace",
35
RunE: func(cmd *cobra.Command, args []string) (err error) {
36
cmd.SilenceUsage = true
37
38
ctx, cancel := context.WithTimeout(cmd.Context(), 5*time.Second)
39
defer cancel()
40
41
tkn, err := idpToken(ctx, idpTokenOpts.Audience, idpTokenOpts.Scope)
42
43
token, _, err := jwt.NewParser().ParseUnverified(tkn, jwt.MapClaims{})
44
if err != nil {
45
return err
46
}
47
48
// If the user wants to decode the token, then do so.
49
if idpTokenOpts.Decode {
50
51
output := map[string]interface{}{
52
"Header": token.Header,
53
"Payload": token.Claims,
54
}
55
56
// The header and payload are then marshalled into a map and printed to the screen.
57
outputPretty, err := json.MarshalIndent(output, "", " ")
58
if err != nil {
59
return xerrors.Errorf("Failed to marshal output: %w", err)
60
}
61
62
fmt.Printf("%s\n", outputPretty)
63
return nil
64
}
65
fmt.Println(tkn)
66
return nil
67
},
68
}
69
70
func idpToken(ctx context.Context, audience []string, scope string) (idToken string, err error) {
71
wsInfo, err := gitpod.GetWSInfo(ctx)
72
if err != nil {
73
return "", err
74
}
75
supervisorConn, err := grpc.Dial(util.GetSupervisorAddress(), grpc.WithTransportCredentials(insecure.NewCredentials()))
76
if err != nil {
77
return "", xerrors.Errorf("failed connecting to supervisor: %w", err)
78
}
79
defer supervisorConn.Close()
80
clientToken, err := supervisor.NewTokenServiceClient(supervisorConn).GetToken(ctx, &supervisor.GetTokenRequest{
81
Host: wsInfo.GitpodApi.Host,
82
Kind: "gitpod",
83
Scope: []string{
84
"function:getWorkspace",
85
},
86
})
87
if err != nil {
88
return "", xerrors.Errorf("failed getting token from supervisor: %w", err)
89
}
90
91
c, err := client.New(client.WithCredentials(clientToken.Token), client.WithURL("https://api."+wsInfo.GitpodApi.Host))
92
if err != nil {
93
return "", err
94
}
95
tkn, err := c.IdentityProvider.GetIDToken(ctx, &connect.Request[v1.GetIDTokenRequest]{
96
Msg: &v1.GetIDTokenRequest{
97
Audience: audience,
98
WorkspaceId: wsInfo.WorkspaceId,
99
Scope: scope,
100
},
101
})
102
if err != nil {
103
return "", err
104
}
105
return tkn.Msg.Token, nil
106
}
107
108
func init() {
109
idpCmd.AddCommand(idpTokenCmd)
110
111
idpTokenCmd.Flags().StringArrayVar(&idpTokenOpts.Audience, "audience", nil, "audience of the ID token")
112
_ = idpTokenCmd.MarkFlagRequired("audience")
113
114
idpTokenCmd.Flags().BoolVar(&idpTokenOpts.Decode, "decode", false, "decode token to JSON")
115
idpTokenCmd.Flags().StringVar(&idpTokenOpts.Scope, "scope", "", "scopes string of the ID token")
116
}
117
118