mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-12-25 23:49:37 -05:00
174 lines
4.4 KiB
Go
174 lines
4.4 KiB
Go
//go:build integration
|
|
|
|
/*
|
|
Copyright (c) Edgeless Systems GmbH
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only
|
|
*/
|
|
|
|
package integration
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"testing"
|
|
|
|
"github.com/edgelesssys/constellation/v2/csi/cryptmapper"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/goleak"
|
|
)
|
|
|
|
const (
|
|
DevicePath string = "testDevice"
|
|
DeviceName string = "testDeviceName"
|
|
)
|
|
|
|
func setup() {
|
|
_ = exec.Command("/bin/dd", "if=/dev/zero", fmt.Sprintf("of=%s", DevicePath), "bs=64M", "count=1").Run()
|
|
}
|
|
|
|
func teardown(devicePath string) {
|
|
_ = exec.Command("/bin/rm", "-f", devicePath).Run()
|
|
}
|
|
|
|
func copy(source, target string) error {
|
|
return exec.Command("cp", source, target).Run()
|
|
}
|
|
|
|
func resize() {
|
|
_ = exec.Command("/bin/dd", "if=/dev/zero", fmt.Sprintf("of=%s", DevicePath), "bs=32M", "count=1", "oflag=append", "conv=notrunc").Run()
|
|
}
|
|
|
|
func TestMain(m *testing.M) {
|
|
if os.Getuid() != 0 {
|
|
fmt.Printf("This test suite requires root privileges, as libcryptsetup uses the kernel's device mapper.\n")
|
|
os.Exit(1)
|
|
}
|
|
|
|
goleak.VerifyTestMain(m)
|
|
|
|
result := m.Run()
|
|
os.Exit(result)
|
|
}
|
|
|
|
func TestOpenAndClose(t *testing.T) {
|
|
assert := assert.New(t)
|
|
require := require.New(t)
|
|
setup()
|
|
defer teardown(DevicePath)
|
|
|
|
mapper := cryptmapper.New(&fakeKMS{}, &cryptmapper.CryptDevice{})
|
|
|
|
newPath, err := mapper.OpenCryptDevice(context.Background(), DevicePath, DeviceName, false)
|
|
require.NoError(err)
|
|
assert.Equal("/dev/mapper/"+DeviceName, newPath)
|
|
|
|
// assert crypt device got created
|
|
_, err = os.Stat(newPath)
|
|
assert.NoError(err)
|
|
// assert no integrity device got created
|
|
_, err = os.Stat(newPath + "_dif")
|
|
assert.True(os.IsNotExist(err))
|
|
|
|
// Resize the device
|
|
resize()
|
|
|
|
resizedPath, err := mapper.ResizeCryptDevice(context.Background(), DeviceName)
|
|
require.NoError(err)
|
|
assert.Equal("/dev/mapper/"+DeviceName, resizedPath)
|
|
|
|
assert.NoError(mapper.CloseCryptDevice(DeviceName))
|
|
|
|
// assert crypt device got removed
|
|
_, err = os.Stat(newPath)
|
|
assert.True(os.IsNotExist(err))
|
|
|
|
// check if we can reopen the device
|
|
_, err = mapper.OpenCryptDevice(context.Background(), DevicePath, DeviceName, true)
|
|
assert.NoError(err)
|
|
assert.NoError(mapper.CloseCryptDevice(DeviceName))
|
|
}
|
|
|
|
func TestOpenAndCloseIntegrity(t *testing.T) {
|
|
assert := assert.New(t)
|
|
require := require.New(t)
|
|
setup()
|
|
defer teardown(DevicePath)
|
|
|
|
mapper := cryptmapper.New(&fakeKMS{}, &cryptmapper.CryptDevice{})
|
|
|
|
newPath, err := mapper.OpenCryptDevice(context.Background(), DevicePath, DeviceName, true)
|
|
require.NoError(err)
|
|
assert.Equal("/dev/mapper/"+DeviceName, newPath)
|
|
|
|
// assert crypt device got created
|
|
_, err = os.Stat(newPath)
|
|
assert.NoError(err)
|
|
// assert integrity device got created
|
|
_, err = os.Stat(newPath + "_dif")
|
|
assert.NoError(err)
|
|
|
|
// integrity devices do not support resizing
|
|
resize()
|
|
_, err = mapper.ResizeCryptDevice(context.Background(), DeviceName)
|
|
assert.Error(err)
|
|
|
|
assert.NoError(mapper.CloseCryptDevice(DeviceName))
|
|
|
|
// assert crypt device got removed
|
|
_, err = os.Stat(newPath)
|
|
assert.True(os.IsNotExist(err))
|
|
// assert integrity device got removed
|
|
_, err = os.Stat(newPath + "_dif")
|
|
assert.True(os.IsNotExist(err))
|
|
|
|
// check if we can reopen the device
|
|
_, err = mapper.OpenCryptDevice(context.Background(), DevicePath, DeviceName, true)
|
|
assert.NoError(err)
|
|
assert.NoError(mapper.CloseCryptDevice(DeviceName))
|
|
}
|
|
|
|
func TestDeviceCloning(t *testing.T) {
|
|
assert := assert.New(t)
|
|
require := require.New(t)
|
|
setup()
|
|
defer teardown(DevicePath)
|
|
|
|
mapper := cryptmapper.New(&dynamicKMS{}, &cryptmapper.CryptDevice{})
|
|
|
|
_, err := mapper.OpenCryptDevice(context.Background(), DevicePath, DeviceName, false)
|
|
assert.NoError(err)
|
|
|
|
require.NoError(copy(DevicePath, DevicePath+"-copy"))
|
|
defer teardown(DevicePath + "-copy")
|
|
|
|
_, err = mapper.OpenCryptDevice(context.Background(), DevicePath+"-copy", DeviceName+"-copy", false)
|
|
assert.NoError(err)
|
|
|
|
assert.NoError(mapper.CloseCryptDevice(DeviceName))
|
|
assert.NoError(mapper.CloseCryptDevice(DeviceName + "-copy"))
|
|
}
|
|
|
|
type fakeKMS struct{}
|
|
|
|
func (k *fakeKMS) GetDEK(ctx context.Context, dekID string, dekSize int) ([]byte, error) {
|
|
key := make([]byte, dekSize)
|
|
for i := range key {
|
|
key[i] = 0x41
|
|
}
|
|
return key, nil
|
|
}
|
|
|
|
type dynamicKMS struct{}
|
|
|
|
func (k *dynamicKMS) GetDEK(ctx context.Context, dekID string, dekSize int) ([]byte, error) {
|
|
key := make([]byte, dekSize)
|
|
for i := range key {
|
|
key[i] = 0x41 ^ dekID[i%len(dekID)]
|
|
}
|
|
return key, nil
|
|
}
|