Raw
 1package replica
 2
 3import (
 4	"fmt"
 5	"strings"
 6
 7	"golang.org/x/crypto/ssh"
 8)
 9
10func ParseAllowedSigners(data []byte) ([]ssh.PublicKey, error) {
11	var keys []ssh.PublicKey
12	for n, line := range strings.Split(string(data), "\n") {
13		line = strings.TrimSpace(line)
14		if line == "" || strings.HasPrefix(line, "#") {
15			continue
16		}
17		i := strings.IndexAny(line, " \t")
18		if i < 0 {
19			return nil, fmt.Errorf("replica: allowed signers line %d: no key", n+1)
20		}
21		key, _, options, _, err := ssh.ParseAuthorizedKey([]byte(strings.TrimSpace(line[i:])))
22		if err != nil {
23			return nil, fmt.Errorf("replica: allowed signers line %d: %w", n+1, err)
24		}
25		if signsGit(options) {
26			keys = append(keys, key)
27		}
28	}
29	if len(keys) == 0 {
30		return nil, ErrNoAllowedKeys
31	}
32	return keys, nil
33}
34
35func signsGit(options []string) bool {
36	for _, o := range options {
37		if o == "cert-authority" {
38			return false
39		}
40		if v, ok := strings.CutPrefix(o, "namespaces="); ok {
41			for _, ns := range strings.Split(strings.Trim(v, `"`), ",") {
42				if ns == Namespace {
43					return true
44				}
45			}
46			return false
47		}
48	}
49	return true
50}