Skip to content
File

Blob: util/migrator/migrator.go

go91 lines
1package migrator
2 
3import (
4 "bytes"
5 "crypto/tls"
6 _ "embed"
7 "net/http"
8 
9 "go.miragespace.co/specter/spec/pki"
10 "go.miragespace.co/specter/tun/client"
11 
12 "github.com/go-chi/chi/v5"
13 "go.uber.org/zap"
14 "go.yaml.in/yaml/v3"
15)
16 
17type v1ClientConfig struct {
18 Apex string `yaml:"apex" json:"apex"`
19 Token string `yaml:"token,omitempty"`
20 ClientID uint64 `yaml:"clientId,omitempty"`
21 Tunnels []client.Tunnel `yaml:"tunnels,omitempty"`
22}
23 
24//go:embed helper.html
25var helper []byte
26 
27func ConfigMigratorHandler(logger *zap.Logger, ca tls.Certificate) http.Handler {
28 router := chi.NewRouter()
29 
30 router.Get("/", func(w http.ResponseWriter, r *http.Request) {
31 w.Header().Set("content-type", "text/html; charset=utf-8")
32 w.Write(helper)
33 })
34 
35 router.Post("/", func(w http.ResponseWriter, r *http.Request) {
36 migrateConfig(logger, ca, w, r)
37 })
38 
39 return router
40}
41 
42func migrateConfig(logger *zap.Logger, ca tls.Certificate, w http.ResponseWriter, r *http.Request) {
43 v1Cfg := v1ClientConfig{}
44 
45 err := yaml.NewDecoder(r.Body).Decode(&v1Cfg)
46 if err != nil {
47 http.Error(w, err.Error(), 400)
48 return
49 }
50 
51 if v1Cfg.ClientID == 0 || len(v1Cfg.Token) != 44 {
52 http.Error(w, "provided yaml is not a valid v1 config", 400)
53 return
54 }
55 
56 certPubKey, keyPem := pki.GeneratePrivKey()
57 
58 certBytes, err := pki.GenerateCertificate(logger, ca, pki.IdentityRequest{
59 PublicKey: certPubKey,
60 Subject: pki.MakeSubjectV1(v1Cfg.ClientID, v1Cfg.Token),
61 })
62 
63 if err != nil {
64 http.Error(w, err.Error(), 500)
65 return
66 }
67 
68 certPem := pki.MarshalCertificate(certBytes)
69 
70 newCfg := client.Config{
71 Version: 2,
72 Apex: v1Cfg.Apex,
73 Certificate: string(certPem),
74 PrivKey: keyPem,
75 Tunnels: v1Cfg.Tunnels,
76 }
77 
78 var out bytes.Buffer
79 encoder := yaml.NewEncoder(&out)
80 encoder.SetIndent(2)
81 err = encoder.Encode(&newCfg)
82 if err != nil {
83 http.Error(w, err.Error(), 500)
84 return
85 }
86 
87 w.Header().Set("content-type", "application/yaml; charset=utf-8")
88 w.WriteHeader(200)
89 w.Write(out.Bytes())
90}