installer: welcome
diff --git a/core/installer/cmd/env_manager.go b/core/installer/cmd/env_manager.go
index 4279445..33b4058 100644
--- a/core/installer/cmd/env_manager.go
+++ b/core/installer/cmd/env_manager.go
@@ -100,12 +100,9 @@
}
type createEnvReq struct {
- Name string `json:"name"`
- ContactEmail string `json:"contactEmail"`
- Domain string `json:"domain"`
- GandiAPIToken string `json:"gandiAPIToken"`
- AdminUsername string `json:"adminUsername"`
- // TODO(giolekva): take admin password as well
+ Name string `json:"name"`
+ ContactEmail string `json:"contactEmail"`
+ Domain string `json:"domain"`
}
func (s *envServer) createEnv(c echo.Context) error {
@@ -135,7 +132,7 @@
if repo == nil {
return err
}
- if err := initNewEnv(installer.NewRepoIO(repo, s.ss.Signer), req); err != nil {
+ if err := initNewEnv(s.ss, installer.NewRepoIO(repo, s.ss.Signer), req); err != nil {
return err
}
}
@@ -160,7 +157,7 @@
return nil
}
-func initNewEnv(r installer.RepoIO, req createEnvReq) error {
+func initNewEnv(ss *soft.Client, r installer.RepoIO, req createEnvReq) error {
appManager, err := installer.NewAppManager(r)
if err != nil {
return err
@@ -236,9 +233,16 @@
if err != nil {
return err
}
- if err := appManager.Install(*app, map[string]any{
- "GandiAPIToken": req.GandiAPIToken,
- }); err != nil {
+ if err := appManager.Install(*app, map[string]any{}); err != nil {
+ return err
+ }
+ }
+ {
+ app, err := appsRepo.Find("certificate-issuer-public")
+ if err != nil {
+ return err
+ }
+ if err := appManager.Install(*app, map[string]any{}); err != nil {
return err
}
}
@@ -265,19 +269,28 @@
}
}
{
- app, err := appsRepo.Find("tailscale-proxy")
+ keys, err := installer.NewSSHKeyPair()
+ if err != nil {
+ return err
+ }
+ user := fmt.Sprintf("%s-welcome", req.Name)
+ if err := ss.AddUser(user, keys.Public); err != nil {
+ return err
+ }
+ if err := ss.AddCollaborator(req.Name, user); err != nil {
+ return err
+ }
+ app, err := appsRepo.Find("welcome")
if err != nil {
return err
}
if err := appManager.Install(*app, map[string]any{
- "Username": req.AdminUsername,
- "IPSubnet": "10.1.0.0/24",
+ "RepoAddr": ss.GetRepoAddress(req.Name),
+ "SSHPrivateKey": keys.Private,
}); err != nil {
return err
}
- // TODO(giolekva): headscale accept routes
}
-
return nil
}
diff --git a/core/installer/cmd/main.go b/core/installer/cmd/main.go
index e82b338..8a5e04b 100644
--- a/core/installer/cmd/main.go
+++ b/core/installer/cmd/main.go
@@ -27,6 +27,7 @@
rootCmd.AddCommand(installCmd())
rootCmd.AddCommand(appManagerCmd())
rootCmd.AddCommand(envManagerCmd())
+ rootCmd.AddCommand(welcomeCmd())
}
func main() {
diff --git a/core/installer/cmd/welcome.go b/core/installer/cmd/welcome.go
new file mode 100644
index 0000000..3b834b0
--- /dev/null
+++ b/core/installer/cmd/welcome.go
@@ -0,0 +1,85 @@
+package main
+
+import (
+ "fmt"
+ "golang.org/x/crypto/ssh"
+ "net"
+ "os"
+
+ "github.com/go-git/go-billy/v5/memfs"
+ "github.com/go-git/go-git/v5"
+ gitssh "github.com/go-git/go-git/v5/plumbing/transport/ssh"
+ "github.com/go-git/go-git/v5/storage/memory"
+ "github.com/spf13/cobra"
+
+ "github.com/giolekva/pcloud/core/installer"
+ "github.com/giolekva/pcloud/core/installer/welcome"
+)
+
+var welcomeFlags struct {
+ repo string
+ sshKey string
+ port int
+}
+
+func welcomeCmd() *cobra.Command {
+ cmd := &cobra.Command{
+ Use: "welcome",
+ RunE: welcomeCmdRun,
+ }
+ cmd.Flags().StringVar(
+ &welcomeFlags.repo,
+ "repo-addr",
+ "",
+ "",
+ )
+ cmd.Flags().StringVar(
+ &welcomeFlags.sshKey,
+ "ssh-key",
+ "",
+ "",
+ )
+ cmd.Flags().IntVar(
+ &welcomeFlags.port,
+ "port",
+ 8080,
+ "",
+ )
+ return cmd
+}
+
+func welcomeCmdRun(cmd *cobra.Command, args []string) error {
+ sshKey, err := os.ReadFile(welcomeFlags.sshKey)
+ if err != nil {
+ return err
+ }
+ auth := authSSH(sshKey)
+ repo, err := git.Clone(memory.NewStorage(), memfs.New(), &git.CloneOptions{
+ URL: welcomeFlags.repo,
+ Auth: auth,
+ RemoteName: "origin",
+ ReferenceName: "refs/heads/master",
+ Depth: 1,
+ InsecureSkipTLS: true,
+ Progress: os.Stdout,
+ })
+ s := welcome.NewServer(
+ welcomeFlags.port,
+ installer.NewRepoIO(repo, auth.Signer),
+ )
+ s.Start()
+ return nil
+}
+
+func authSSH(pemBytes []byte) *gitssh.PublicKeys {
+ a, err := gitssh.NewPublicKeys("git", pemBytes, "")
+ if err != nil {
+ panic(err)
+ }
+ a.HostKeyCallback = func(hostname string, remote net.Addr, key ssh.PublicKey) error {
+ // TODO(giolekva): verify server public key
+ fmt.Printf("--- %+v\n", ssh.MarshalAuthorizedKey(key))
+ return nil
+ }
+ return a
+}