forked from Diniboy1123/usque
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathenroll.go
More file actions
147 lines (125 loc) · 4.38 KB
/
enroll.go
File metadata and controls
147 lines (125 loc) · 4.38 KB
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package cmd
import (
"crypto/x509"
"encoding/base64"
"fmt"
"log"
"github.com/Diniboy1123/usque/api"
"github.com/Diniboy1123/usque/config"
"github.com/Diniboy1123/usque/internal"
"github.com/Diniboy1123/usque/models"
"github.com/spf13/cobra"
)
var enrollCmd = &cobra.Command{
Use: "enroll",
Short: "Enrolls a MASQUE private key and switches mode",
Long: "Enrolls a MASQUE private key and switches mode. Useful for ZeroTier where IPv6 address can change." +
" Or if you just want to deploy a new key.",
Run: func(cmd *cobra.Command, args []string) {
if !config.ConfigLoaded {
cmd.Println("Config not loaded. Please register first.")
return
}
configPath, err := cmd.Flags().GetString("config")
if err != nil {
log.Fatalf("Failed to get config path: %v", err)
}
if configPath == "" {
log.Fatalf("Config path is required")
}
deviceName, err := cmd.Flags().GetString("name")
if err != nil {
log.Fatalf("Failed to get device name: %v", err)
}
regenKey, err := cmd.Flags().GetBool("regen-key")
if err != nil {
log.Fatalf("Failed to get regen-key: %v", err)
}
log.Printf("Enrolling device key...")
accountData := models.AccountData{
Token: config.AppConfig.AccessToken,
ID: config.AppConfig.ID,
}
var (
privKeyBytes []byte
publicKey []byte
)
if regenKey {
log.Printf("Regenerating key pair...")
privKeyBytes, publicKey, err = internal.GenerateEcKeyPair()
if err != nil {
log.Fatalf("Failed to generate key pair: %v", err)
}
} else {
privKey, err := config.AppConfig.GetEcPrivateKey()
if err != nil {
log.Fatalf("Failed to get private key: %v", err)
}
publicKey, err = x509.MarshalPKIXPublicKey(&privKey.PublicKey)
if err != nil {
log.Fatalf("Failed to marshal public key: %v", err)
}
privKeyBytes, err = x509.MarshalECPrivateKey(privKey)
if err != nil {
log.Fatalf("Failed to marshal private key: %v", err)
}
}
updatedAccountData, apiErr, err := api.EnrollKey(accountData, publicKey, deviceName)
if err != nil {
if apiErr != nil && apiErr.HasErrorMessage(models.InvalidPublicKey) {
fmt.Print("Invalid public key detected. Regenerate key? (y/n): ")
var response string
if _, err := fmt.Scanln(&response); err != nil {
log.Fatalf("Failed to read user input: %v", err)
}
if response == "y" {
log.Printf("Regenerating key pair...")
privKeyBytes, publicKey, err = internal.GenerateEcKeyPair()
if err != nil {
log.Fatalf("Failed to generate key pair: %v", err)
}
log.Println("Re-enrolling device key with new key pair...")
updatedAccountData, apiErr, err = api.EnrollKey(accountData, publicKey, deviceName)
if err != nil {
if apiErr != nil {
log.Fatalf("Failed to enroll key: %v (API errors: %s)", err, apiErr.ErrorsAsString("; "))
}
log.Fatalf("Failed to enroll key: %v", err)
}
} else {
log.Fatalf("Enrollment aborted by user. API errors: %s", apiErr.ErrorsAsString("; "))
}
} else {
log.Fatalf("Failed to enroll key: %v (API errors: %s)", err, apiErr.ErrorsAsString("; "))
}
}
log.Printf("Successful registration. Saving config...")
h2v4 := config.AppConfig.EndpointH2V4
if h2v4 == "" {
h2v4 = config.DefaultEndpointH2V4
}
config.AppConfig = config.Config{
PrivateKey: base64.StdEncoding.EncodeToString(privKeyBytes),
// TODO: proper endpoint parsing in utils
// strip :0
EndpointV4: updatedAccountData.Config.Peers[0].Endpoint.V4[:len(updatedAccountData.Config.Peers[0].Endpoint.V4)-2],
// strip [ from beginning and ]:0 from end
EndpointV6: updatedAccountData.Config.Peers[0].Endpoint.V6[1 : len(updatedAccountData.Config.Peers[0].Endpoint.V6)-3],
EndpointH2V4: h2v4,
EndpointH2V6: config.AppConfig.EndpointH2V6,
EndpointPubKey: updatedAccountData.Config.Peers[0].PublicKey,
License: updatedAccountData.Account.License,
ID: updatedAccountData.ID,
AccessToken: accountData.Token,
IPv4: updatedAccountData.Config.Interface.Addresses.V4,
IPv6: updatedAccountData.Config.Interface.Addresses.V6,
}
config.AppConfig.SaveConfig(configPath)
log.Printf("Config saved to %s", configPath)
},
}
func init() {
enrollCmd.Flags().StringP("name", "n", "", "Rename device a given name")
enrollCmd.Flags().BoolP("regen-key", "r", false, "Regenerate the key pair")
rootCmd.AddCommand(enrollCmd)
}