mirror of
https://github.com/podman-container-tools/podman.git
synced 2026-10-14 18:07:43 +00:00
Hyper-V VMs require some specific Windows registry keys to allow the communication between the host and the guest. Creating these registry keys require elevated privileges. These keys were created during the first Podman `machine init` and removed when the last Podman machine is removed. In this commit we skip the creation of the keys if they already exist in the registry. So that admin privileges aren't required anymore, even for the creation of the first Podman machine. In other words, if the keys are pre-created by an administrator, user will be able to create and remove machines without requiring to run any elevated command. Even for the first podman machine. Signed-off-by: Mario Loriedo <mario.loriedo@gmail.com>
180 lines
4.8 KiB
Go
180 lines
4.8 KiB
Go
//go:build windows
|
|
|
|
package hyperv
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"go.podman.io/podman/v6/pkg/machine/hyperv/vsock"
|
|
"go.podman.io/podman/v6/pkg/machine/vmconfigs"
|
|
)
|
|
|
|
func TestCanCreate(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
isElevated bool
|
|
vsockEntriesExist bool
|
|
isHyperVAdmin bool
|
|
mounts int
|
|
expectedErr error
|
|
}{
|
|
{
|
|
name: "in elevated process can always create",
|
|
isElevated: true,
|
|
vsockEntriesExist: false,
|
|
isHyperVAdmin: false,
|
|
mounts: 2,
|
|
expectedErr: nil,
|
|
},
|
|
{
|
|
name: "not elevated, no vsock entries",
|
|
isElevated: false,
|
|
vsockEntriesExist: false,
|
|
isHyperVAdmin: true,
|
|
expectedErr: ErrHypervRegistryInitRequiresElevation,
|
|
},
|
|
{
|
|
name: "not elevated, vsock entries exist, not hyperv admin",
|
|
isElevated: false,
|
|
vsockEntriesExist: true,
|
|
isHyperVAdmin: false,
|
|
expectedErr: ErrHypervUserNotInAdminGroup,
|
|
},
|
|
{
|
|
name: "not elevated, vsock entries exist, hyperv admin",
|
|
isElevated: false,
|
|
vsockEntriesExist: true,
|
|
isHyperVAdmin: true,
|
|
expectedErr: nil,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
checks := permissionChecks{
|
|
isElevatedProcess: func() bool { return tt.isElevated },
|
|
isHyperVAdminMember: func() bool { return tt.isHyperVAdmin },
|
|
vsockEntriesExist: func(int) bool { return tt.vsockEntriesExist },
|
|
}
|
|
|
|
err := checkCanCreate(checks, tt.mounts)
|
|
assert.ErrorIs(t, err, tt.expectedErr)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCanRemove(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
isElevatedProcess bool
|
|
isHyperVAdminMember bool
|
|
isLegacyMachine bool
|
|
skipVsockEntriesRemoval bool
|
|
isLastMachine bool
|
|
expectedErr error
|
|
}{
|
|
{
|
|
name: "elevated process can always remove",
|
|
isElevatedProcess: true,
|
|
isHyperVAdminMember: false,
|
|
isLegacyMachine: false,
|
|
skipVsockEntriesRemoval: false,
|
|
isLastMachine: true,
|
|
expectedErr: nil,
|
|
},
|
|
{
|
|
name: "not elevated, legacy machine requires elevation",
|
|
isElevatedProcess: false,
|
|
isHyperVAdminMember: false,
|
|
isLegacyMachine: true,
|
|
skipVsockEntriesRemoval: false,
|
|
isLastMachine: true,
|
|
expectedErr: ErrHypervLegacyMachineRequiresElevation,
|
|
},
|
|
{
|
|
name: "not elevated, not hyperv admins member",
|
|
isElevatedProcess: false,
|
|
isHyperVAdminMember: false,
|
|
isLegacyMachine: false,
|
|
skipVsockEntriesRemoval: false,
|
|
isLastMachine: true,
|
|
expectedErr: ErrHypervUserNotInAdminGroup,
|
|
},
|
|
{
|
|
name: "not elevated, hyperv admins member, not last machine",
|
|
isElevatedProcess: false,
|
|
isHyperVAdminMember: true,
|
|
isLegacyMachine: false,
|
|
skipVsockEntriesRemoval: false,
|
|
isLastMachine: false,
|
|
expectedErr: nil,
|
|
},
|
|
{
|
|
name: "not elevated, hyperv admins member, last machine, skip vsock entries removal",
|
|
isElevatedProcess: false,
|
|
isHyperVAdminMember: true,
|
|
isLegacyMachine: false,
|
|
skipVsockEntriesRemoval: true,
|
|
isLastMachine: true,
|
|
expectedErr: nil,
|
|
},
|
|
{
|
|
name: "not elevated, hyperv admins member, last machine, don't skip vsock entries removal",
|
|
isElevatedProcess: false,
|
|
isHyperVAdminMember: true,
|
|
isLegacyMachine: false,
|
|
skipVsockEntriesRemoval: false,
|
|
isLastMachine: true,
|
|
expectedErr: ErrHypervRegistryRemoveRequiresElevation,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
checks := permissionChecks{
|
|
isElevatedProcess: func() bool { return tt.isElevatedProcess },
|
|
isHyperVAdminMember: func() bool { return tt.isHyperVAdminMember },
|
|
existingMachinesNum: func() (int, error) {
|
|
if tt.isLastMachine {
|
|
return 1, nil
|
|
} else {
|
|
return 2, nil
|
|
}
|
|
},
|
|
}
|
|
|
|
vsockMachineName := ""
|
|
if tt.isLegacyMachine {
|
|
vsockMachineName = "podmanmachine"
|
|
}
|
|
|
|
mc := &vmconfigs.MachineConfig{
|
|
HyperVHypervisor: &vmconfigs.HyperVConfig{
|
|
ReadyVsock: vsock.HVSockRegistryEntry{
|
|
MachineName: vsockMachineName,
|
|
KeepAfterMachineRemove: tt.skipVsockEntriesRemoval,
|
|
},
|
|
NetworkVSock: vsock.HVSockRegistryEntry{
|
|
KeepAfterMachineRemove: tt.skipVsockEntriesRemoval,
|
|
},
|
|
},
|
|
}
|
|
|
|
err := checkCanRemove(mc, checks)
|
|
if tt.expectedErr != nil {
|
|
assert.EqualError(t, err, tt.expectedErr.Error())
|
|
} else {
|
|
assert.NoError(t, err)
|
|
}
|
|
})
|
|
}
|
|
}
|