check / check (push) Waiting to run
A restore by a normal user always warned that file ownership was not preserved, even when every recorded owner and group were the restoring user's own, so ownership came out exactly as backed up. The warning is now printed only when some entry to restore is recorded with another owner or group than the restoring user's effective ids. A restore as root never warns, as before. The tests pass the restoring user's ids in, since make test runs as root. Judgement call: an entry that failed to restore still counts. Judgement call: a recorded group that is another of the user's groups still warns, since restore changes no group as a normal user. Model: opus-5-5
98 lines
2.2 KiB
Go
98 lines
2.2 KiB
Go
package vaultik //nolint:testpackage // calls the unexported ownership check
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/spf13/afero"
|
|
"github.com/stretchr/testify/assert"
|
|
"sneak.berlin/go/vaultik/internal/database"
|
|
"sneak.berlin/go/vaultik/internal/log"
|
|
"sneak.berlin/go/vaultik/internal/ui"
|
|
)
|
|
|
|
// These tests cover https://git.eeqj.de/sneak/vaultik/issues/316: a
|
|
// restore by a normal user warns that ownership was not preserved only
|
|
// when some entry's recorded owner or group differs from the restoring
|
|
// user's. The restoring user's ids are passed in, because make test runs
|
|
// as root.
|
|
|
|
const (
|
|
restoringUserID = 1000
|
|
restoringGroupID = 1000
|
|
rootUserID = 0
|
|
otherOwnedPath = "/other"
|
|
)
|
|
|
|
func TestRestoreOwnershipWarning(t *testing.T) {
|
|
log.Initialize(log.Config{})
|
|
t.Parallel()
|
|
|
|
ownFile := &database.File{
|
|
Path: "/own", UID: restoringUserID, GID: restoringGroupID,
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
files []*database.File
|
|
uid int
|
|
wantWarn bool
|
|
}{
|
|
{
|
|
name: "every owner matches",
|
|
files: []*database.File{
|
|
ownFile,
|
|
{Path: "/own/dir", UID: restoringUserID, GID: restoringGroupID},
|
|
},
|
|
uid: restoringUserID,
|
|
wantWarn: false,
|
|
},
|
|
{
|
|
name: "another owner",
|
|
files: []*database.File{
|
|
ownFile,
|
|
{Path: otherOwnedPath, UID: otherOwnerID, GID: restoringGroupID},
|
|
},
|
|
uid: restoringUserID,
|
|
wantWarn: true,
|
|
},
|
|
{
|
|
name: "another group",
|
|
files: []*database.File{
|
|
ownFile,
|
|
{Path: otherOwnedPath, UID: restoringUserID, GID: otherOwnerID},
|
|
},
|
|
uid: restoringUserID,
|
|
wantWarn: true,
|
|
},
|
|
{
|
|
name: "root restores another owner",
|
|
files: []*database.File{
|
|
{Path: otherOwnedPath, UID: otherOwnerID, GID: otherOwnerID},
|
|
},
|
|
uid: rootUserID,
|
|
wantWarn: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var out bytes.Buffer
|
|
|
|
v := newContainmentVaultik(context.Background(), afero.NewMemMapFs())
|
|
v.UI = ui.NewWithColor(&out, false)
|
|
|
|
v.warnIfOwnershipNotPreserved(tt.files, tt.uid, restoringGroupID)
|
|
|
|
if tt.wantWarn {
|
|
assert.Contains(t, out.String(), "did not preserve file ownership")
|
|
} else {
|
|
assert.Empty(t, out.String())
|
|
}
|
|
})
|
|
}
|
|
}
|