/
login.go
91 lines (76 loc) · 2.4 KB
/
login.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package cli
import (
"context"
"fmt"
"net"
"os"
"path"
"github.com/defang-io/defang/src/pkg/cli/client"
"github.com/defang-io/defang/src/pkg/github"
"github.com/defang-io/defang/src/pkg/term"
defangv1 "github.com/defang-io/defang/src/protos/io/defang/v1"
)
func getTokenFile(fabric string) string {
if host, _, _ := net.SplitHostPort(fabric); host != "" {
fabric = host
}
return path.Join(client.StateDir, fabric)
}
func GetExistingToken(fabric string) string {
var accessToken = os.Getenv("DEFANG_ACCESS_TOKEN")
if accessToken == "" {
tokenFile := getTokenFile(fabric)
term.Debug(" - Reading access token from file", tokenFile)
all, _ := os.ReadFile(tokenFile)
accessToken = string(all)
} else {
term.Debug(" - Using access token from env DEFANG_ACCESS_TOKEN")
}
return accessToken
}
func loginWithGitHub(ctx context.Context, client client.Client, gitHubClientId, fabric string) (string, error) {
term.Debug(" - Logging in to", fabric)
code, err := github.StartAuthCodeFlow(ctx, gitHubClientId)
if err != nil {
return "", err
}
tenant, _ := SplitTenantHost(fabric)
return exchangeCodeForToken(ctx, client, code, tenant, 0) // no scopes = unrestricted
}
func saveAccessToken(fabric, at string) error {
tokenFile := getTokenFile(fabric)
term.Debug(" - Saving access token to", tokenFile)
os.MkdirAll(client.StateDir, 0700)
if err := os.WriteFile(tokenFile, []byte(at), 0600); err != nil {
return err
}
return nil
}
func InteractiveLogin(ctx context.Context, client client.Client, gitHubClientId, fabric string) error {
at, err := loginWithGitHub(ctx, client, gitHubClientId, fabric)
if err != nil {
return err
}
tenant, host := SplitTenantHost(fabric)
term.Info(" * Successfully logged in to", host, "("+tenant.String()+" tenant)")
if err := saveAccessToken(fabric, at); err != nil {
term.Warn(" ! Failed to save access token:", err)
}
return nil
}
func NonInteractiveLogin(ctx context.Context, client client.Client, fabric string) error {
term.Debug(" - Non-interactive login using GitHub Actions id-token")
idToken, err := github.GetIdToken(ctx)
if err != nil {
return fmt.Errorf("non-interactive login failed: %w", err)
}
term.Debug(" - Got GitHub Actions id-token")
resp, err := client.Token(ctx, &defangv1.TokenRequest{
Assertion: idToken,
Scope: []string{"admin", "read"},
})
if err != nil {
return err
}
return saveAccessToken(fabric, resp.AccessToken)
}