Fixes and cleanup after implementation of the S3 and SSH roadmap

This commit is contained in:
2026-05-31 14:33:17 -05:00
parent 1d71a151cc
commit 7eed1a26ae
13 changed files with 250 additions and 59 deletions

View File

@@ -208,9 +208,10 @@ func (b *Backend) Walk(ctx context.Context, logicalPrefix string, opts storage.W
} else if err != nil {
return err
}
return nil
}
if !storage.IsNotFound(err) {
if opts.Limit > 0 && visited >= opts.Limit {
return nil
}
} else if !storage.IsNotFound(err) {
return err
}
}

View File

@@ -66,6 +66,63 @@ func TestStatRequiresExactObject(t *testing.T) {
}
}
func TestWalkIncludesExactObjectAndDescendants(t *testing.T) {
client := newFakeClient(map[string]string{
"root/bundle": "marker",
"root/bundle/report.md": "report",
})
backend := newTestBackend(t, "root", client)
entries, err := storage.List(context.Background(), backend, "bundle", storage.WalkOptions{Recursive: true})
if err != nil {
t.Fatalf("List() error = %v", err)
}
paths := entryPaths(entries)
if got, want := paths, []string{"bundle", "bundle/report.md"}; !equalStrings(got, want) {
t.Fatalf("paths = %v, want %v", got, want)
}
}
func TestWalkExactObjectHonorsLimitBeforeListingDescendants(t *testing.T) {
client := newFakeClient(map[string]string{
"root/bundle": "marker",
"root/bundle/report.md": "report",
})
backend := newTestBackend(t, "root", client)
var entries []storage.Entry
err := backend.Walk(context.Background(), "bundle", storage.WalkOptions{Recursive: true, Limit: 1}, func(entry storage.Entry) error {
entries = append(entries, entry)
return nil
})
if err != nil {
t.Fatalf("Walk() error = %v", err)
}
paths := entryPaths(entries)
if got, want := paths, []string{"bundle"}; !equalStrings(got, want) {
t.Fatalf("paths = %v, want %v", got, want)
}
if len(client.tokens) != 0 {
t.Fatalf("list calls = %d, want none", len(client.tokens))
}
}
func TestHasAnyWithExactObjectStopsBeforeListingDescendants(t *testing.T) {
client := newFakeClient(map[string]string{
"root/bundle": "marker",
"root/bundle/report.md": "report",
})
backend := newTestBackend(t, "root", client)
found, err := backend.HasAny(context.Background(), "bundle")
if err != nil {
t.Fatalf("HasAny() error = %v", err)
}
if !found {
t.Fatal("HasAny() = false, want true")
}
if len(client.tokens) != 0 {
t.Fatalf("list calls = %d, want none", len(client.tokens))
}
}
func TestWriteFromChecksOverwriteBeforePut(t *testing.T) {
client := newFakeClient(map[string]string{"root/report.md": "old"})
backend := newTestBackend(t, "root", client)

View File

@@ -54,6 +54,9 @@ func acceptNewHostKeyCallback(options Options) (cryptossh.HostKeyCallback, error
return fmt.Errorf("host key for %s has changed: %w", hostname, err)
}
}
if options.ReadOnlyKnownHosts {
return nil
}
if options.KnownHosts == "" {
return fmt.Errorf("host key for %s is unknown and no writable known_hosts path is available", hostname)
}

View File

@@ -36,6 +36,25 @@ func TestAcceptNewHostKeyCallbackPersistsUnknownHost(t *testing.T) {
}
}
func TestAcceptNewHostKeyCallbackReadOnlyDoesNotPersistUnknownHost(t *testing.T) {
key := testPublicKey(t)
knownHosts := filepath.Join(t.TempDir(), "known_hosts")
callback, err := acceptNewHostKeyCallback(Options{
KnownHosts: knownHosts,
ReadOnlyKnownHosts: true,
})
if err != nil {
t.Fatalf("acceptNewHostKeyCallback() error = %v", err)
}
if err := callback("example.com:22", &net.TCPAddr{IP: net.ParseIP("192.0.2.10"), Port: 22}, key); err != nil {
t.Fatalf("callback() error = %v", err)
}
if _, err := os.Stat(knownHosts); !os.IsNotExist(err) {
t.Fatalf("known_hosts stat error = %v, want not exist", err)
}
}
func TestAcceptNewHostKeyCallbackRejectsChangedHostKey(t *testing.T) {
first := testPublicKey(t)
second := testPublicKey(t)
@@ -54,6 +73,27 @@ func TestAcceptNewHostKeyCallbackRejectsChangedHostKey(t *testing.T) {
}
}
func TestAcceptNewHostKeyCallbackReadOnlyRejectsChangedHostKey(t *testing.T) {
first := testPublicKey(t)
second := testPublicKey(t)
knownHosts := filepath.Join(t.TempDir(), "known_hosts")
if err := os.WriteFile(knownHosts, []byte(knownhosts.Line([]string{knownhosts.Normalize("example.com:22")}, first)+"\n"), 0o600); err != nil {
t.Fatalf("write known_hosts: %v", err)
}
callback, err := acceptNewHostKeyCallback(Options{
KnownHosts: knownHosts,
ReadOnlyKnownHosts: true,
})
if err != nil {
t.Fatalf("acceptNewHostKeyCallback() error = %v", err)
}
err = callback("example.com:22", &net.TCPAddr{IP: net.ParseIP("192.0.2.10"), Port: 22}, second)
if err == nil || !strings.Contains(err.Error(), "has changed") {
t.Fatalf("callback() error = %v, want changed host key", err)
}
}
func TestAcceptNewHostKeyCallbackRequiresWritableKnownHostsForUnknownHost(t *testing.T) {
callback, err := acceptNewHostKeyCallback(Options{})
if err != nil {
@@ -66,6 +106,17 @@ func TestAcceptNewHostKeyCallbackRequiresWritableKnownHostsForUnknownHost(t *tes
}
}
func TestAcceptNewHostKeyCallbackReadOnlyAllowsMissingKnownHosts(t *testing.T) {
callback, err := acceptNewHostKeyCallback(Options{ReadOnlyKnownHosts: true})
if err != nil {
t.Fatalf("acceptNewHostKeyCallback() error = %v", err)
}
if err := callback("example.com:22", &net.TCPAddr{IP: net.ParseIP("192.0.2.10"), Port: 22}, testPublicKey(t)); err != nil {
t.Fatalf("callback() error = %v", err)
}
}
func TestStrictHostKeyCallbackRequiresKnownHosts(t *testing.T) {
_, err := hostKeyCallback(Options{HostKeyPolicy: HostKeyPolicyStrict})
if err == nil || !strings.Contains(err.Error(), "known_hosts is required") {

View File

@@ -20,13 +20,14 @@ const (
type HostKeyPolicy string
type Options struct {
Host string
User string
Port int
Root string
KeyFile string
KnownHosts string
HostKeyPolicy HostKeyPolicy
Host string
User string
Port int
Root string
KeyFile string
KnownHosts string
HostKeyPolicy HostKeyPolicy
ReadOnlyKnownHosts bool
}
func (o Options) normalized() (Options, error) {