Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

Code

395 commit(s) on main

update readme Keenan Nemetz · 27m ago 32290114
history blame raw 3.8 KiB
1package client
2
3// The host-key policy is the thing that decides which instance a runner trusts,
4// so it is worth pinning: strict unless the caller says otherwise, and an
5// environment variable cannot loosen it.
6
7import (
8 "os"
9 "strings"
10 "testing"
11)
12
13func argv(t *testing.T, host, port string, args ...string) []string {
14 t.Helper()
15 return SSHCommand(host, port, args...).Args
16}
17
18func containsOption(args []string, want string) bool {
19 for i := 0; i+1 < len(args); i++ {
20 if args[i] == "-o" && args[i+1] == want {
21 return true
22 }
23 }
24 return false
25}
26
27func TestSSHCommandVerifiesHostKeysByDefault(t *testing.T) {
28 SetHostKeys(HostKeys{})
29 t.Cleanup(func() { SetHostKeys(HostKeys{}) })
30 t.Setenv("GIT_SSH_COMMAND", "")
31 t.Setenv("VOLE_SSH_COMMAND", "")
32
33 got := argv(t, "git@forge.example.com", "2222", "vole-whoami")
34 if !containsOption(got, "StrictHostKeyChecking=yes") {
35 t.Fatalf("no strict host-key check in %q", got)
36 }
37 if containsOption(got, "UserKnownHostsFile=/dev/null") {
38 t.Fatalf("the default policy discards known_hosts: %q", got)
39 }
40}
41
42func TestSSHCommandUsesTheConfiguredKnownHosts(t *testing.T) {
43 SetHostKeys(HostKeys{KnownHosts: "/etc/vole/known_hosts"})
44 t.Cleanup(func() { SetHostKeys(HostKeys{}) })
45 got := argv(t, "git@forge.example.com", "", "vole-whoami")
46 if !containsOption(got, "StrictHostKeyChecking=yes") ||
47 !containsOption(got, "UserKnownHostsFile=/etc/vole/known_hosts") {
48 t.Fatalf("the known_hosts policy is not applied: %q", got)
49 }
50}
51
52// A configured ssh command may carry its own options; ours go first because ssh
53// takes the first value for an option, so an environment variable cannot turn the
54// check off behind the caller's back.
55func TestSSHCommandKeepsHostKeyCheckingAheadOfTheEnvironment(t *testing.T) {
56 SetHostKeys(HostKeys{})
57 t.Cleanup(func() { SetHostKeys(HostKeys{}) })
58 t.Setenv("GIT_SSH_COMMAND", "ssh -i /tmp/key -o StrictHostKeyChecking=no")
59 got := argv(t, "git@forge.example.com", "", "vole-whoami")
60 strict, loose := -1, -1
61 for i := 0; i+1 < len(got); i++ {
62 if got[i] != "-o" {
63 continue
64 }
65 switch got[i+1] {
66 case "StrictHostKeyChecking=yes":
67 if strict < 0 {
68 strict = i
69 }
70 case "StrictHostKeyChecking=no":
71 if loose < 0 {
72 loose = i
73 }
74 }
75 }
76 if strict < 0 || loose < 0 {
77 t.Fatalf("expected both options in %q", got)
78 }
79 if strict > loose {
80 t.Fatalf("the environment's StrictHostKeyChecking=no comes first in %q", got)
81 }
82 if !containsOption(got, "IdentitiesOnly=yes") && !strings.Contains(strings.Join(got, " "), "-i /tmp/key") {
83 t.Fatalf("the configured key was dropped: %q", got)
84 }
85}
86
87func TestSSHCommandInsecureIsExplicit(t *testing.T) {
88 SetHostKeys(HostKeys{Insecure: true})
89 t.Cleanup(func() { SetHostKeys(HostKeys{}) })
90 got := argv(t, "git@forge.example.com", "", "vole-whoami")
91 if !containsOption(got, "StrictHostKeyChecking=no") ||
92 !containsOption(got, "UserKnownHostsFile=/dev/null") {
93 t.Fatalf("the explicit override is not applied: %q", got)
94 }
95}
96
97func TestHostKeysFromEnv(t *testing.T) {
98 t.Setenv("VOLE_KNOWN_HOSTS", " /tmp/kh ")
99 t.Setenv("VOLE_INSECURE_HOST_KEY", "1")
100 h := HostKeysFromEnv()
101 if h.KnownHosts != "/tmp/kh" || !h.Insecure {
102 t.Fatalf("HostKeysFromEnv() = %+v", h)
103 }
104 t.Setenv("VOLE_INSECURE_HOST_KEY", "")
105 h = HostKeysFromEnv()
106 if h.Insecure {
107 t.Fatalf("an empty VOLE_INSECURE_HOST_KEY enabled the override: %+v", h)
108 }
109}
110
111func TestGitSSHCommandCarriesThePolicy(t *testing.T) {
112 SetHostKeys(HostKeys{KnownHosts: "/tmp/kh"})
113 t.Cleanup(func() { SetHostKeys(HostKeys{}) })
114 t.Setenv("GIT_SSH_COMMAND", "ssh -i /key")
115 got := GitSSHCommand()
116 for _, want := range []string{"ssh", "-o StrictHostKeyChecking=yes", "UserKnownHostsFile=/tmp/kh", "-i /key"} {
117 if !strings.Contains(got, want) {
118 t.Fatalf("GitSSHCommand() = %q, missing %q", got, want)
119 }
120 }
121 if os.Getenv("GIT_SSH_COMMAND") != "ssh -i /key" {
122 t.Fatal("GitSSHCommand modified the environment")
123 }
124}
125