krz/gitbay
A CLI-first git forge.
clone: git clone https://gitbay.org/krz/gitbay.git
repo-descriptions: cmd/gitbayd/system.go · raw
1package main
2
3import (
4 "fmt"
5 "os"
6
7 "github.com/spf13/cobra"
8 "golang.org/x/crypto/ssh"
9
10 "gitbay.org/gitbay/internal/config"
11 "gitbay.org/gitbay/internal/protocol"
12 "gitbay.org/gitbay/internal/sshd"
13)
14
15// authorizedKeysCmd backs sshd's AuthorizedKeysCommand in system mode:
16//
17// AuthorizedKeysCommand /usr/bin/gitbayd --config /etc/gitbay/config.toml authorized-keys %t %k
18// AuthorizedKeysCommandUser git
19//
20// It prints a forced-command authorized_keys line for registered keys and
21// nothing for unknown ones — so unknown keys fail authentication inside
22// sshd, before any forge code runs. That is why system mode requires
23// registration = "closed".
24func authorizedKeysCmd() *cobra.Command {
25 return &cobra.Command{
26 Use: "authorized-keys <key-type> <key-base64>",
27 Hidden: true,
28 Args: cobra.ExactArgs(2),
29 RunE: func(cmd *cobra.Command, args []string) error {
30 cfg, err := config.Load(configPath)
31 if err != nil {
32 return err
33 }
34 st, err := openStore(cfg)
35 if err != nil {
36 return err
37 }
38 defer st.Close()
39
40 pub, _, _, _, err := ssh.ParseAuthorizedKey([]byte(args[0] + " " + args[1]))
41 if err != nil {
42 return nil // unparseable key: no output, auth fails
43 }
44 key, err := st.SSHKeyByFingerprint(ssh.FingerprintSHA256(pub))
45 if err != nil {
46 return nil // unknown key: no output, auth fails
47 }
48 self, err := os.Executable()
49 if err != nil {
50 return err
51 }
52 fmt.Printf("restrict,command=\"%s --config %s shell --key-id %d\" %s %s\n",
53 self, configPath, key.ID, args[0], args[1])
54 return nil
55 },
56 }
57}
58
59// shellCmd is the forced command sshd runs for an authenticated key. The
60// original client command arrives in SSH_ORIGINAL_COMMAND; dispatch is the
61// same code path as the embedded listener.
62func shellCmd() *cobra.Command {
63 var keyID int64
64 cmd := &cobra.Command{
65 Use: "shell",
66 Hidden: true,
67 Args: cobra.NoArgs,
68 RunE: func(cmd *cobra.Command, args []string) error {
69 cfg, err := config.Load(configPath)
70 if err != nil {
71 return err
72 }
73 st, err := openStore(cfg)
74 if err != nil {
75 return err
76 }
77 defer st.Close()
78
79 key, err := st.SSHKeyByID(keyID)
80 if err != nil {
81 fmt.Fprintln(os.Stderr, "key no longer registered")
82 os.Exit(protocol.ExitDenied)
83 }
84 user, err := st.UserByID(key.UserID)
85 if err != nil {
86 fmt.Fprintln(os.Stderr, "account no longer exists")
87 os.Exit(protocol.ExitDenied)
88 }
89 _ = st.TouchSSHKey(key.ID)
90
91 cmdline := os.Getenv("SSH_ORIGINAL_COMMAND")
92 if cmdline == "" {
93 fmt.Fprintf(os.Stderr, "gitbay control plane: interactive shells are not available.\nTry: ssh <host> help\n")
94 os.Exit(protocol.ExitUsage)
95 }
96 code := sshd.Exec(cfg, st, user, key.Scope, cmdline, os.Stdin, os.Stdout, os.Stderr)
97 st.Close()
98 os.Exit(code)
99 return nil
100 },
101 }
102 cmd.Flags().Int64Var(&keyID, "key-id", 0, "registered key id (set by authorized-keys)")
103 cmd.MarkFlagRequired("key-id")
104 return cmd
105}