tangled
alpha
login
or
join now
tjh.dev
/
core
forked from
tangled.org/core
0
fork
atom
this repo has no description
0
fork
atom
overview
issues
pulls
pipelines
keyfetch: add keyfetch and internal api
anirudh.fi
1 year ago
96840b4d
22aa04d5
verified
This commit was signed with the committer's
known signature
.
anirudh.fi
SSH Key Fingerprint:
SHA256:FQUiBXeyBQT4WKOm7EKh6hLkHjBh9MdfkV3my0dueGE=
+225
-14
11 changed files
expand all
collapse all
unified
split
cmd
keyfetch
format.go
format_test.go
main.go
legit
main.go
repoguard
main.go
config
config.go
config.yaml
db
pubkeys.go
routes
handler.go
internal.go
routes.go
+15
cmd/keyfetch/format.go
···
1
1
+
package main
2
2
+
3
3
+
import (
4
4
+
"fmt"
5
5
+
)
6
6
+
7
7
+
func formatKeyData(repoguardPath string, data map[string]string) string {
8
8
+
var result string
9
9
+
for user, key := range data {
10
10
+
result += fmt.Sprintf(
11
11
+
`command="%s -base-dir /home/git -user %s -log-path /home/git/log ",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty %s`+"\n",
12
12
+
repoguardPath, user, key)
13
13
+
}
14
14
+
return result
15
15
+
}
+45
cmd/keyfetch/format_test.go
···
1
1
+
package main
2
2
+
3
3
+
import "testing"
4
4
+
5
5
+
func TestFormatKeyData(t *testing.T) {
6
6
+
tests := []struct {
7
7
+
name string
8
8
+
repoguardPath string
9
9
+
data map[string]string
10
10
+
want string
11
11
+
}{
12
12
+
{
13
13
+
name: "single user",
14
14
+
repoguardPath: "/usr/bin/repoguard",
15
15
+
data: map[string]string{
16
16
+
"user1": "ssh-rsa AAAA...",
17
17
+
},
18
18
+
want: `command="/usr/bin/repoguard -base-dir /home/git -user user1 -log-path /home/git/log ",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAA...` + "\n",
19
19
+
},
20
20
+
{
21
21
+
name: "multiple users",
22
22
+
repoguardPath: "/usr/bin/repoguard",
23
23
+
data: map[string]string{
24
24
+
"user1": "ssh-rsa AAAA...",
25
25
+
"user2": "ssh-rsa BBBB...",
26
26
+
},
27
27
+
want: `command="/usr/bin/repoguard -base-dir /home/git -user user1 -log-path /home/git/log ",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAA...` + "\n" +
28
28
+
`command="/usr/bin/repoguard -base-dir /home/git -user user2 -log-path /home/git/log ",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa BBBB...` + "\n",
29
29
+
},
30
30
+
{
31
31
+
name: "empty data",
32
32
+
repoguardPath: "/usr/bin/repoguard",
33
33
+
data: map[string]string{},
34
34
+
want: "",
35
35
+
},
36
36
+
}
37
37
+
38
38
+
for _, tt := range tests {
39
39
+
t.Run(tt.name, func(t *testing.T) {
40
40
+
if got := formatKeyData(tt.repoguardPath, tt.data); got != tt.want {
41
41
+
t.Errorf("formatKeyData() = %v, want %v", got, tt.want)
42
42
+
}
43
43
+
})
44
44
+
}
45
45
+
}
+35
cmd/keyfetch/main.go
···
1
1
+
package main
2
2
+
3
3
+
import (
4
4
+
"encoding/json"
5
5
+
"flag"
6
6
+
"fmt"
7
7
+
"io"
8
8
+
"log"
9
9
+
"net/http"
10
10
+
)
11
11
+
12
12
+
func main() {
13
13
+
endpoint := flag.String("internal-api", "http://localhost:5444", "Internal API endpoint")
14
14
+
repoguardPath := flag.String("repoguard-path", "/home/git/repoguard", "Path to the repoguard binary")
15
15
+
flag.Parse()
16
16
+
17
17
+
resp, err := http.Get(*endpoint + "/internal/allkeys")
18
18
+
if err != nil {
19
19
+
log.Fatalf("error fetching keys: %v", err)
20
20
+
}
21
21
+
defer resp.Body.Close()
22
22
+
23
23
+
body, err := io.ReadAll(resp.Body)
24
24
+
if err != nil {
25
25
+
log.Fatalf("error reading response body: %v", err)
26
26
+
}
27
27
+
28
28
+
var data map[string]string
29
29
+
err = json.Unmarshal(body, &data)
30
30
+
if err != nil {
31
31
+
log.Fatalf("error unmarshalling response body: %v", err)
32
32
+
}
33
33
+
34
34
+
fmt.Print(formatKeyData(*repoguardPath, data))
35
35
+
}
+15
-3
cmd/legit/main.go
···
9
9
"os"
10
10
11
11
"github.com/icyphox/bild/config"
12
12
+
"github.com/icyphox/bild/db"
12
13
"github.com/icyphox/bild/routes"
13
14
)
14
15
···
23
24
if err != nil {
24
25
log.Fatal(err)
25
26
}
27
27
+
db, err := db.Setup(c.Server.DBPath)
28
28
+
if err != nil {
29
29
+
log.Fatalf("failed to setup db: %s", err)
30
30
+
}
26
31
27
27
-
mux, err := routes.Setup(c)
32
32
+
mux, err := routes.Setup(c, db)
28
33
if err != nil {
29
34
log.Fatal(err)
30
35
}
36
36
+
37
37
+
internalMux := routes.SetupInternal(c, db)
31
38
32
39
addr := fmt.Sprintf("%s:%d", c.Server.Host, c.Server.Port)
33
33
-
log.Println("starting server on", addr)
34
34
-
log.Fatal(http.ListenAndServe(addr, mux))
40
40
+
internalAddr := fmt.Sprintf("%s:%d", c.Server.InternalHost, c.Server.InternalPort)
41
41
+
42
42
+
log.Println("starting main server on", addr)
43
43
+
go http.ListenAndServe(addr, mux)
44
44
+
45
45
+
log.Println("starting internal server on", internalAddr)
46
46
+
log.Fatal(http.ListenAndServe(internalAddr, internalMux))
35
47
}
+10
-2
cmd/repoguard/main.go
···
143
143
}
144
144
145
145
func isAllowedUser(user, repoPath string) bool {
146
146
-
pathUser := strings.Split(repoPath, "/")[0]
147
147
-
return pathUser == user
146
146
+
fullPath := filepath.Join(*baseDirFlag, repoPath)
147
147
+
didPath := filepath.Join(fullPath, "did")
148
148
+
149
149
+
didBytes, err := os.ReadFile(didPath)
150
150
+
if err != nil {
151
151
+
return false
152
152
+
}
153
153
+
154
154
+
allowedUser := strings.TrimSpace(string(didBytes))
155
155
+
return allowedUser == user
148
156
}
+2
config.yaml
···
19
19
host: 0.0.0.0
20
20
port: 5555
21
21
dbpath: bild.db
22
22
+
internalHost: 127.0.0.1
23
23
+
internalPort: 5444
+3
config/config.go
···
30
30
Host string `yaml:"host"`
31
31
Port int `yaml:"port"`
32
32
DBPath string `yaml:"dbpath"`
33
33
+
34
34
+
InternalHost string `yaml:"internalHost,omitempty"`
35
35
+
InternalPort int `yaml:"internalPort,omitempty"`
33
36
} `yaml:"server"`
34
37
}
35
38
+27
-2
db/pubkeys.go
···
17
17
type PublicKey struct {
18
18
Key string
19
19
Name string
20
20
+
DID string
20
21
Created time.Time
21
22
}
22
23
24
24
+
func (d *DB) GetAllPublicKeys() ([]PublicKey, error) {
25
25
+
var keys []PublicKey
26
26
+
27
27
+
rows, err := d.db.Query(`select key, name, did, created from public_keys`)
28
28
+
if err != nil {
29
29
+
return nil, err
30
30
+
}
31
31
+
defer rows.Close()
32
32
+
33
33
+
for rows.Next() {
34
34
+
var publicKey PublicKey
35
35
+
if err := rows.Scan(&publicKey.Key, &publicKey.Name, &publicKey.DID, &publicKey.Created); err != nil {
36
36
+
return nil, err
37
37
+
}
38
38
+
keys = append(keys, publicKey)
39
39
+
}
40
40
+
41
41
+
if err := rows.Err(); err != nil {
42
42
+
return nil, err
43
43
+
}
44
44
+
45
45
+
return keys, nil
46
46
+
}
47
47
+
23
48
func (d *DB) GetPublicKeys(did string) ([]PublicKey, error) {
24
49
var keys []PublicKey
25
50
26
26
-
rows, err := d.db.Query(`select key, name, created from public_keys where did = ?`, did)
51
51
+
rows, err := d.db.Query(`select did, key, name, created from public_keys where did = ?`, did)
27
52
if err != nil {
28
53
return nil, err
29
54
}
···
31
56
32
57
for rows.Next() {
33
58
var publicKey PublicKey
34
34
-
if err := rows.Scan(&publicKey.Key, &publicKey.Name, &publicKey.Created); err != nil {
59
59
+
if err := rows.Scan(&publicKey.DID, &publicKey.Key, &publicKey.Name, &publicKey.Created); err != nil {
35
60
return nil, err
36
61
}
37
62
keys = append(keys, publicKey)
+1
-6
routes/handler.go
···
37
37
}
38
38
}
39
39
40
40
-
func Setup(c *config.Config) (http.Handler, error) {
40
40
+
func Setup(c *config.Config, db *db.DB) (http.Handler, error) {
41
41
r := chi.NewRouter()
42
42
s := sessions.NewCookieStore([]byte("TODO_CHANGE_ME"))
43
43
t, err := tmpl.Load(c.Dirs.Templates)
···
46
46
}
47
47
48
48
auth := auth.NewAuth(s)
49
49
-
50
50
-
db, err := db.Setup(c.Server.DBPath)
51
51
-
if err != nil {
52
52
-
return nil, fmt.Errorf("failed to setup db: %w", err)
53
53
-
}
54
49
55
50
h := Handle{
56
51
c: c,
+62
routes/internal.go
···
1
1
+
package routes
2
2
+
3
3
+
import (
4
4
+
"encoding/json"
5
5
+
"net/http"
6
6
+
7
7
+
"github.com/go-chi/chi/v5"
8
8
+
"github.com/icyphox/bild/config"
9
9
+
"github.com/icyphox/bild/db"
10
10
+
)
11
11
+
12
12
+
type InternalHandle struct {
13
13
+
c *config.Config
14
14
+
db *db.DB
15
15
+
}
16
16
+
17
17
+
func SetupInternal(c *config.Config, db *db.DB) http.Handler {
18
18
+
ih := &InternalHandle{
19
19
+
c: c,
20
20
+
db: db,
21
21
+
}
22
22
+
23
23
+
r := chi.NewRouter()
24
24
+
r.Route("/internal/allkeys", func(r chi.Router) {
25
25
+
r.Get("/", ih.AllKeys)
26
26
+
})
27
27
+
28
28
+
return r
29
29
+
}
30
30
+
31
31
+
func (h *InternalHandle) returnJSON(w http.ResponseWriter, data interface{}) error {
32
32
+
w.Header().Set("Content-Type", "application/json")
33
33
+
res, err := json.Marshal(data)
34
34
+
if err != nil {
35
35
+
return err
36
36
+
}
37
37
+
_, err = w.Write(res)
38
38
+
return err
39
39
+
}
40
40
+
41
41
+
func (h *InternalHandle) returnErr(w http.ResponseWriter, err error) error {
42
42
+
w.WriteHeader(http.StatusInternalServerError)
43
43
+
return h.returnJSON(w, map[string]string{
44
44
+
"error": err.Error(),
45
45
+
})
46
46
+
}
47
47
+
48
48
+
func (h *InternalHandle) AllKeys(w http.ResponseWriter, r *http.Request) {
49
49
+
keys, err := h.db.GetAllPublicKeys()
50
50
+
if err != nil {
51
51
+
h.returnErr(w, err)
52
52
+
return
53
53
+
}
54
54
+
keyMap := map[string]string{}
55
55
+
for _, key := range keys {
56
56
+
keyMap[key.DID] = key.Key
57
57
+
}
58
58
+
if err := h.returnJSON(w, keyMap); err != nil {
59
59
+
h.returnErr(w, err)
60
60
+
return
61
61
+
}
62
62
+
}
+10
-1
routes/routes.go
···
524
524
name := r.FormValue("name")
525
525
description := r.FormValue("description")
526
526
527
527
-
err := git.InitBare(filepath.Join(h.c.Repo.ScanPath, handle, name))
527
527
+
repoPath := filepath.Join(h.c.Repo.ScanPath, handle, name)
528
528
+
err := git.InitBare(repoPath)
529
529
+
if err != nil {
530
530
+
h.WriteOOBNotice(w, "repo", "Error creating repo. Try again later.")
531
531
+
return
532
532
+
}
533
533
+
534
534
+
// For use by repoguard
535
535
+
didPath := filepath.Join(repoPath, "did")
536
536
+
err = os.WriteFile(didPath, []byte(did), 0644)
528
537
if err != nil {
529
538
h.WriteOOBNotice(w, "repo", "Error creating repo. Try again later.")
530
539
return