468a99f884c51011251ced2cb8b5debf012e843a
- Author
- Ayman Bagabas <ayman.bagabas@gmail.com>
- Committer
- Ayman Bagabas <ayman.bagabas@gmail.com>
- Date
Message
Diff
This diff is truncated to protect this page.
1diff --git a/cmd/soft/migrate_config.go b/cmd/soft/migrate_config.go
2index 9c4f23e3857a3177e6bb610cc3301a47d33e42e0..200d46547d14c8d3894f0eb39b1ac7808f008715 100644
3--- a/cmd/soft/migrate_config.go
4+++ b/cmd/soft/migrate_config.go
5@@ -23,12 +23,12 @@ var (
6 migrateConfig = &cobra.Command{
7 Use: "migrate-config",
8 Short: "Migrate config to new format",
9- RunE: func(cmd *cobra.Command, args []string) error {
10+ RunE: func(_ *cobra.Command, _ []string) error {
11 keyPath := os.Getenv("SOFT_SERVE_KEY_PATH")
12 reposPath := os.Getenv("SOFT_SERVE_REPO_PATH")
13 bindAddr := os.Getenv("SOFT_SERVE_BIND_ADDRESS")
14 cfg := config.DefaultConfig()
15- sb, err := sqlite.NewSqliteBackend(cfg.DataPath)
16+ sb, err := sqlite.NewSqliteBackend(cfg)
17 if err != nil {
18 return fmt.Errorf("failed to create sqlite backend: %w", err)
19 }
20@@ -72,7 +72,7 @@ var (
21 return fmt.Errorf("failed to get tree: %w", err)
22 }
23
24- isJson := false
25+ isJson := false // nolint: revive
26 te, err := tree.TreeEntry("config.yaml")
27 if err != nil {
28 te, err = tree.TreeEntry("config.json")
29@@ -236,7 +236,7 @@ func isGitDir(path string) bool {
30 return true
31 }
32
33-// copyFile copies a single file from src to dst
34+// copyFile copies a single file from src to dst.
35 func copyFile(src, dst string) error {
36 var err error
37 var srcfd *os.File
38@@ -246,12 +246,12 @@ func copyFile(src, dst string) error {
39 if srcfd, err = os.Open(src); err != nil {
40 return err
41 }
42- defer srcfd.Close()
43+ defer srcfd.Close() // nolint: errcheck
44
45 if dstfd, err = os.Create(dst); err != nil {
46 return err
47 }
48- defer dstfd.Close()
49+ defer dstfd.Close() // nolint: errcheck
50
51 if _, err = io.Copy(dstfd, srcfd); err != nil {
52 return err
53@@ -262,7 +262,7 @@ func copyFile(src, dst string) error {
54 return os.Chmod(dst, srcinfo.Mode())
55 }
56
57-// copyDir copies a whole directory recursively
58+// copyDir copies a whole directory recursively.
59 func copyDir(src string, dst string) error {
60 var err error
61 var fds []os.DirEntry
62@@ -296,112 +296,7 @@ func copyDir(src string, dst string) error {
63 return nil
64 }
65
66-// func copyDir(src, dst string) error {
67-// entries, err := os.ReadDir(src)
68-// if err != nil {
69-// return err
70-// }
71-// for _, entry := range entries {
72-// sourcePath := filepath.Join(src, entry.Name())
73-// destPath := filepath.Join(dst, entry.Name())
74-//
75-// fileInfo, err := os.Stat(sourcePath)
76-// if err != nil {
77-// return err
78-// }
79-//
80-// stat, ok := fileInfo.Sys().(*syscall.Stat_t)
81-// if !ok {
82-// return fmt.Errorf("failed to get raw syscall.Stat_t data for '%s'", sourcePath)
83-// }
84-//
85-// switch fileInfo.Mode() & os.ModeType {
86-// case os.ModeDir:
87-// if err := createIfNotExists(destPath, 0755); err != nil {
88-// return err
89-// }
90-// if err := copyDir(sourcePath, destPath); err != nil {
91-// return err
92-// }
93-// case os.ModeSymlink:
94-// if err := copySymLink(sourcePath, destPath); err != nil {
95-// return err
96-// }
97-// default:
98-// if err := copyFile(sourcePath, destPath); err != nil {
99-// return err
100-// }
101-// }
102-//
103-// if err := os.Lchown(destPath, int(stat.Uid), int(stat.Gid)); err != nil {
104-// return err
105diff --git a/server/backend/sqlite/sqlite.go b/server/backend/sqlite/sqlite.go
106index 5ddb9529ed278f53ce654ba3ed31aa1dd01320d1..1d07652d26b218a656a531115251abb962528d92 100644
107--- a/server/backend/sqlite/sqlite.go
108+++ b/server/backend/sqlite/sqlite.go
109@@ -10,10 +10,10 @@ import (
110 "strings"
111 "text/template"
112
113- "github.com/charmbracelet/keygen"
114 "github.com/charmbracelet/log"
115 "github.com/charmbracelet/soft-serve/git"
116 "github.com/charmbracelet/soft-serve/server/backend"
117+ "github.com/charmbracelet/soft-serve/server/config"
118 "github.com/charmbracelet/soft-serve/server/utils"
119 "github.com/jmoiron/sqlx"
120 _ "modernc.org/sqlite"
121@@ -26,9 +26,9 @@ var (
122 // SqliteBackend is a backend that uses a SQLite database as a Soft Serve
123 // backend.
124 type SqliteBackend struct {
125+ cfg *config.Config
126 dp string
127 db *sqlx.DB
128- ckp string
129 AdditionalAdmins []string
130 }
131
132@@ -39,22 +39,12 @@ func (d *SqliteBackend) reposPath() string {
133 }
134
135 // NewSqliteBackend creates a new SqliteBackend.
136-func NewSqliteBackend(dataPath string) (*SqliteBackend, error) {
137+func NewSqliteBackend(cfg *config.Config) (*SqliteBackend, error) {
138+ dataPath := cfg.DataPath
139 if err := os.MkdirAll(dataPath, 0755); err != nil {
140 return nil, err
141 }
142
143- ckp := filepath.Join(dataPath, "ssh", "soft_serve_client")
144- _, err := keygen.NewWithWrite(ckp, nil, keygen.Ed25519)
145- if err != nil {
146- return nil, err
147- }
148-
149- ckp, err = filepath.Abs(ckp)
150- if err != nil {
151- return nil, err
152- }
153-
154 db, err := sqlx.Connect("sqlite", filepath.Join(dataPath, "soft-serve.db"+
155 "?_pragma=busy_timeout(5000)&_pragma=foreign_keys(1)"))
156 if err != nil {
157@@ -62,9 +52,9 @@ func NewSqliteBackend(dataPath string) (*SqliteBackend, error) {
158 }
159
160 d := &SqliteBackend{
161+ cfg: cfg,
162 dp: dataPath,
163 db: db,
164- ckp: ckp,
165 }
166
167 if err := d.init(); err != nil {
168@@ -186,8 +176,8 @@ func (d *SqliteBackend) ImportRepository(name string, remote string, opts backen
169 CommandOptions: git.CommandOptions{
170 Envs: []string{
171 fmt.Sprintf(`GIT_SSH_COMMAND=ssh -o UserKnownHostsFile="%s" -o StrictHostKeyChecking=no -i "%s"`,
172- filepath.Join(filepath.Dir(d.ckp), "known_hosts"),
173- d.ckp,
174+ filepath.Join(d.cfg.DataPath, "ssh", "known_hosts"),
175+ filepath.Join(d.cfg.DataPath, d.cfg.SSH.ClientKeyPath),
176 ),
177 },
178 },
179diff --git a/server/config/config.go b/server/config/config.go
180index e9295409ac28808e18d576d08e477f04bd6664cf..79ab416df3d5ccc962d3d1f4e5d9d5d1bc0f52df 100644
181--- a/server/config/config.go
182+++ b/server/config/config.go
183@@ -21,6 +21,9 @@ type SSHConfig struct {
184 // KeyPath is the path to the SSH server's private key.
185 KeyPath string `env:"KEY_PATH" yaml:"key_path"`
186
187+ // ClientKeyPath is the path to the SSH server's client private key.
188+ ClientKeyPath string `env:"CLIENT_KEY_PATH" yaml:"client_key_path"`
189+
190 // InternalKeyPath is the path to the SSH server's internal private key.
191 InternalKeyPath string `env:"INTERNAL_KEY_PATH" yaml:"internal_key_path"`
192
193@@ -122,6 +125,11 @@ func DefaultConfig() *Config {
194 dataPath = "data"
195 }
196
197+ dp, _ := filepath.Abs(dataPath)
198+ if dp != "" {
199+ dataPath = dp
200+ }
201+
202 cfg := &Config{
203 Name: "Soft Serve",
204 DataPath: dataPath,
205@@ -129,6 +137,7 @@ func DefaultConfig() *Config {
206 ListenAddr: ":23231",
207 PublicURL: "ssh://localhost:23231",
208 KeyPath: filepath.Join("ssh", "soft_serve_host"),
209+ ClientKeyPath: filepath.Join("ssh", "soft_serve_client"),
210 InternalKeyPath: filepath.Join("ssh", "soft_serve_internal"),
211 MaxTimeout: 0,
212 IdleTimeout: 120,
213diff --git a/server/config/file.go b/server/config/file.go
214index 8f295cf6abfddcf9d1b403a7ecdebe1cd9583d3b..f85c7247b564ce3d2c1f9a8ae65f70ff0849bccb 100644
215--- a/server/config/file.go
216+++ b/server/config/file.go
217@@ -24,6 +24,11 @@ ssh:
218 # The relative path to the SSH server's private key.
219 key_path: "{{ .SSH.KeyPath }}"
220
221+ # The relative path to the SSH server's client private key.
222+ # This key will be used to authenticate the server to make git requests to
223+ # ssh remotes.
224+ client_key_path: "{{ .SSH.ClientKeyPath }}"
225+
226 # The relative path to the SSH server's internal api private key.
227 internal_key_path: "{{ .SSH.InternalKeyPath }}"
228
229diff --git a/server/daemon_test.go b/server/daemon_test.go
230index 79b30d9959347ea179df6dd2970bd7280fc77e45..1e324dbb8387d9d1b291ce6d95aeef5c4f9903fe 100644
231--- a/server/daemon_test.go
232+++ b/server/daemon_test.go
233@@ -30,15 +30,16 @@ func TestMain(m *testing.M) {
234 os.Setenv("SOFT_SERVE_GIT_MAX_TIMEOUT", "100")
235 os.Setenv("SOFT_SERVE_GIT_IDLE_TIMEOUT", "1")
236 os.Setenv("SOFT_SERVE_GIT_LISTEN_ADDR", fmt.Sprintf(":%d", randomPort()))
237- fb, err := sqlite.NewSqliteBackend(tmp)
238+ cfg := config.DefaultConfig()
239+ d, err := NewGitDaemon(cfg)
240 if err != nil {
241 log.Fatal(err)
242 }
243- cfg := config.DefaultConfig().WithBackend(fb)
244- d, err := NewGitDaemon(cfg)
245+ fb, err := sqlite.NewSqliteBackend(cfg)
246 if err != nil {
247 log.Fatal(err)
248 }
249+ cfg = cfg.WithBackend(fb)
250 testDaemon = d
251 go func() {
252 if err := d.Start(); err != ErrServerClosed {
253diff --git a/server/jobs.go b/server/jobs.go
254index df5fb0cc0d875ad01167207f141cad939ea524c2..6320a8f1b79d05eb5700f5039668ffd50cfed001 100644
255--- a/server/jobs.go
256+++ b/server/jobs.go
257@@ -1,8 +1,11 @@
258 package server
259
260 import (
261+ "fmt"
262+ "path/filepath"
263+
264 "github.com/charmbracelet/soft-serve/git"
265- "github.com/charmbracelet/soft-serve/server/backend"
266+ "github.com/charmbracelet/soft-serve/server/config"
267 )
268
269 var (
270@@ -12,7 +15,8 @@ var (
271 )
272
273 // mirrorJob runs the (pull) mirror job task.
274-func mirrorJob(b backend.Backend) func() {
275+func mirrorJob(cfg *config.Config) func() {
276+ b := cfg.Backend
277 logger := logger.WithPrefix("server.mirrorJob")
278 return func() {
279 repos, err := b.Repositories()
280@@ -31,6 +35,12 @@ func mirrorJob(b backend.Backend) func() {
281 }
282
283 cmd := git.NewCommand("remote", "update", "--prune")
284+ cmd.AddEnvs(
285+ fmt.Sprintf(`GIT_SSH_COMMAND=ssh -o UserKnownHostsFile="%s" -o StrictHostKeyChecking=no -i "%s"`,
286+ filepath.Join(cfg.DataPath, "ssh", "known_hosts"),
287+ filepath.Join(cfg.DataPath, cfg.SSH.ClientKeyPath),
288+ ),
289+ )
290 if _, err := cmd.RunInDir(r.Path); err != nil {
291 logger.Error("error running git remote update", "repo", repo.Name(), "err", err)
292 }
293diff --git a/server/server.go b/server/server.go
294index eac408ebd670fc72eb17070c287a2d21b9bc119d..de227c54287853bf5cbb73a7bdeb1e68b52809d9 100644
295--- a/server/server.go
296+++ b/server/server.go
297@@ -39,7 +39,7 @@ type Server struct {
298 func NewServer(cfg *config.Config) (*Server, error) {
299 var err error
300 if cfg.Backend == nil {
301- sb, err := sqlite.NewSqliteBackend(cfg.DataPath)
302+ sb, err := sqlite.NewSqliteBackend(cfg)
303 if err != nil {
304 logger.Fatal(err)
305 }
306@@ -57,6 +57,16 @@ func NewServer(cfg *config.Config) (*Server, error) {
307 if err != nil {
308 return nil, err
309 }
310+
311+ // Create client key.
312+ _, err = keygen.NewWithWrite(
313+ filepath.Join(cfg.DataPath, cfg.SSH.ClientKeyPath),
314+ nil,
315+ keygen.Ed25519,
316+ )
317+ if err != nil {
318+ return nil, err
319+ }
320 }
321
322 srv := &Server{
323@@ -66,7 +76,7 @@ func NewServer(cfg *config.Config) (*Server, error) {
324 }
325
326 // Add cron jobs.
327- srv.Cron.AddFunc(jobSpecs["mirror"], mirrorJob(cfg.Backend))
328+ srv.Cron.AddFunc(jobSpecs["mirror"], mirrorJob(cfg))
329
330 srv.SSHServer, err = NewSSHServer(cfg, srv)
331 if err != nil {
332diff --git a/server/session_test.go b/server/session_test.go
333index 1e6b6d8b781ad7b6f804f7dad2feefa3a84bf8f8..1e5b74fdbe90ec481535128de427750f8f34873c 100644
334--- a/server/session_test.go
335+++ b/server/session_test.go
336@@ -51,11 +51,12 @@ func setup(tb testing.TB) *gossh.Session {
337 is.NoErr(os.Unsetenv("SOFT_SERVE_SSH_LISTEN_ADDR"))
338 is.NoErr(os.RemoveAll(dp))
339 })
340- fb, err := sqlite.NewSqliteBackend(dp)
341+ cfg := config.DefaultConfig()
342+ fb, err := sqlite.NewSqliteBackend(cfg)
343 if err != nil {
344 log.Fatal(err)
345 }
346- cfg := config.DefaultConfig().WithBackend(fb)
347+ cfg = cfg.WithBackend(fb)
348 return testsession.New(tb, &ssh.Server{
349 Handler: bm.MiddlewareWithProgramHandler(SessionHandler(cfg), termenv.ANSI256)(func(s ssh.Session) {
350 _, _, active := s.Pty()