1package config
2
3import (
4 "strings"
5 "unicode"
6
7 "tug/internal/platform/userbasekeys"
8)
9
10const (
11 reasonConfigKnownHostsUnused = "set only when remote is an ssh:// URL"
12 reasonBranch = "must be a branch name without \"..\", \"//\", a leading or trailing \"/\", spaces, control characters or any of ~^:?*[\\, and not HEAD"
13)
14
15func (v *validator) configGit(g *rawConfigGit) *ConfigGit {
16 if g == nil {
17 g = &rawConfigGit{}
18 }
19 remoteValid := v.required("config.git.remote", g.Remote) && v.remote("config.git.remote", g.Remote)
20 if v.required("config.git.branch", g.Branch) {
21 v.branch("config.git.branch", g.Branch)
22 }
23 if v.required("config.git.allowed_signers", g.AllowedSigners) {
24 v.absolutePath("config.git.allowed_signers", g.AllowedSigners)
25 }
26 switch {
27 case !remoteValid:
28 case v.idx.has("config.git.known_hosts") && !usesSSH(g.Remote):
29 v.add("config.git.known_hosts", reasonConfigKnownHostsUnused)
30 case v.idx.has("config.git.known_hosts"):
31 v.absolutePath("config.git.known_hosts", g.KnownHosts)
32 case usesSSH(g.Remote):
33 v.add("config.git.known_hosts", reasonRequired)
34 }
35 return &ConfigGit{Remote: g.Remote, Branch: g.Branch, AllowedSigners: g.AllowedSigners, KnownHosts: g.KnownHosts}
36}
37
38func (v *validator) branch(key, value string) {
39 ok := value != "HEAD" && !strings.Contains(value, "..") && !strings.Contains(value, "//") &&
40 !strings.HasPrefix(value, "/") && !strings.HasSuffix(value, "/") && !strings.ContainsAny(value, "~^:?*[\\")
41 for _, r := range value {
42 if unicode.IsControl(r) || unicode.IsSpace(r) {
43 ok = false
44 }
45 }
46 if !ok {
47 v.add(key, reasonBranch)
48 }
49}
50
51func (g *ConfigGit) SSH() bool {
52 return usesSSH(g.Remote)
53}
54
55func checkConfigSecrets(file string, vars map[string]secretLine, s Secrets) []Problem {
56 if s.ConfigDeployKey.isZero() {
57 return nil
58 }
59 if _, err := userbasekeys.ParseSigner(s.ConfigDeployKey.Bytes()); err != nil {
60 return []Problem{{File: file, Line: vars[nameConfigRepoKey].line, Key: nameConfigRepoKey, Reason: keyFileReason(err)}}
61 }
62 return nil
63}