Skip to content

Commit bb8d2c8

Browse files
cryptsetup: enable detached header (edgelesssys#3927)
* deps: update go-cryptsetup * cryptsetup: use detached headers when opening existing crypt devices * cryptsetup: only activate disks with detached header --------- Signed-off-by: Daniel Weiße <[email protected]>
1 parent 23fa3bb commit bb8d2c8

File tree

10 files changed

+682
-100
lines changed

10 files changed

+682
-100
lines changed

csi/test/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ go_test(
1414
"@e2fsprogs//:bin/mkfs.ext4",
1515
"@util-linux//:bin/blkid",
1616
"@util-linux//:bin/fsck",
17+
"@util-linux//:bin/losetup",
1718
"@util-linux//:bin/mount",
1819
"@util-linux//:bin/umount",
1920
],
@@ -23,6 +24,7 @@ go_test(
2324
"DD": "$(rlocationpath @coreutils//:bin/dd)",
2425
"FSCK": "$(rlocationpath @util-linux//:bin/fsck)",
2526
"FSCK_EXT4": "$(rlocationpath @e2fsprogs//:bin/fsck.ext4)",
27+
"LOSETUP": "$(rlocationpath @util-linux//:bin/losetup)",
2628
"MKFS_EXT4": "$(rlocationpath @e2fsprogs//:bin/mkfs.ext4)",
2729
"MOUNT": "$(rlocationpath @util-linux//:bin/mount)",
2830
"RM": "$(rlocationpath @coreutils//:bin/rm)",

csi/test/mount_integration_test.go

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ import (
2727
)
2828

2929
const (
30-
devicePath string = "testDevice"
31-
deviceName string = "testDeviceName"
30+
defaultBackingImage = "testDevice"
31+
deviceName = "testDeviceName"
3232
)
3333

34-
var toolsEnvs = []string{"CP", "DD", "RM", "FSCK_EXT4", "MKFS_EXT4", "BLKID", "FSCK", "MOUNT", "UMOUNT"}
34+
var toolsEnvs = []string{"CP", "DD", "RM", "FSCK_EXT4", "MKFS_EXT4", "BLKID", "FSCK", "MOUNT", "UMOUNT", "LOSETUP"}
3535

3636
// addToolsToPATH is used to update the PATH to contain necessary tool binaries for
3737
// coreutils, util-linux and ext4.
@@ -57,20 +57,35 @@ func addToolsToPATH() error {
5757
return nil
5858
}
5959

60-
func setup(devicePath string) {
61-
if err := exec.Command("dd", "if=/dev/zero", fmt.Sprintf("of=%s", devicePath), "bs=64M", "count=1").Run(); err != nil {
60+
func setup(backingDisk string) string {
61+
if err := exec.Command("dd", "if=/dev/zero", fmt.Sprintf("of=%s", backingDisk), "bs=64M", "count=1").Run(); err != nil {
6262
panic(err)
6363
}
64+
out, err := exec.Command("losetup", "-f", "--show", backingDisk).CombinedOutput()
65+
if err != nil {
66+
panic(err)
67+
}
68+
return strings.TrimSpace(string(out))
6469
}
6570

66-
func teardown(devicePath string) {
67-
if err := exec.Command("rm", "-f", devicePath).Run(); err != nil {
71+
func teardown(backingImage, devicePath string) {
72+
if err := exec.Command("losetup", "-d", devicePath).Run(); err != nil {
73+
panic(err)
74+
}
75+
if err := exec.Command("rm", "-f", backingImage).Run(); err != nil {
6876
panic(err)
6977
}
7078
}
7179

72-
func cp(source, target string) error {
73-
return exec.Command("cp", source, target).Run()
80+
func cp(source, target string) (string, error) {
81+
if err := exec.Command("cp", source, target).Run(); err != nil {
82+
return "", err
83+
}
84+
out, err := exec.Command("losetup", "-f", "--show", target).CombinedOutput()
85+
if err != nil {
86+
return "", err
87+
}
88+
return strings.TrimSpace(string(out)), nil
7489
}
7590

7691
func resize(devicePath string) {
@@ -100,8 +115,8 @@ func TestMain(m *testing.M) {
100115
func TestOpenAndClose(t *testing.T) {
101116
assert := assert.New(t)
102117
require := require.New(t)
103-
setup(devicePath)
104-
defer teardown(devicePath)
118+
devicePath := setup(defaultBackingImage)
119+
defer teardown(defaultBackingImage, devicePath)
105120

106121
mapper := cryptmapper.New(&fakeKMS{})
107122

@@ -124,7 +139,7 @@ func TestOpenAndClose(t *testing.T) {
124139
assert.Equal(newPath, newPath2)
125140

126141
// Resize the device
127-
resize(devicePath)
142+
resize(defaultBackingImage)
128143

129144
resizedPath, err := mapper.ResizeCryptDevice(t.Context(), deviceName)
130145
require.NoError(err)
@@ -145,8 +160,8 @@ func TestOpenAndClose(t *testing.T) {
145160
func TestOpenAndCloseIntegrity(t *testing.T) {
146161
assert := assert.New(t)
147162
require := require.New(t)
148-
setup(devicePath)
149-
defer teardown(devicePath)
163+
devicePath := setup(defaultBackingImage)
164+
defer teardown(defaultBackingImage, devicePath)
150165

151166
mapper := cryptmapper.New(&fakeKMS{})
152167

@@ -167,7 +182,7 @@ func TestOpenAndCloseIntegrity(t *testing.T) {
167182
assert.Equal(newPath, newPath2)
168183

169184
// integrity devices do not support resizing
170-
resize(devicePath)
185+
resize(defaultBackingImage)
171186
_, err = mapper.ResizeCryptDevice(t.Context(), deviceName)
172187
assert.Error(err)
173188

@@ -182,25 +197,26 @@ func TestOpenAndCloseIntegrity(t *testing.T) {
182197

183198
// check if we can reopen the device
184199
_, err = mapper.OpenCryptDevice(t.Context(), devicePath, deviceName, true)
185-
assert.NoError(err)
200+
assert.NoError(err, "Failed to re-open crypt device")
186201
assert.NoError(mapper.CloseCryptDevice(deviceName))
187202
}
188203

189204
func TestDeviceCloning(t *testing.T) {
190205
assert := assert.New(t)
191206
require := require.New(t)
192-
setup(devicePath)
193-
defer teardown(devicePath)
207+
devicePath := setup(defaultBackingImage)
208+
defer teardown(defaultBackingImage, devicePath)
194209

195210
mapper := cryptmapper.New(&dynamicKMS{})
196211

197212
_, err := mapper.OpenCryptDevice(t.Context(), devicePath, deviceName, false)
198213
assert.NoError(err)
199214

200-
require.NoError(cp(devicePath, devicePath+"-copy"))
201-
defer teardown(devicePath + "-copy")
215+
cpDevice, err := cp(defaultBackingImage, defaultBackingImage+"-copy")
216+
require.NoError(err)
217+
defer teardown(defaultBackingImage+"-copy", cpDevice)
202218

203-
_, err = mapper.OpenCryptDevice(t.Context(), devicePath+"-copy", deviceName+"-copy", false)
219+
_, err = mapper.OpenCryptDevice(t.Context(), cpDevice, deviceName+"-copy", false)
204220
assert.NoError(err)
205221

206222
assert.NoError(mapper.CloseCryptDevice(deviceName))
@@ -209,12 +225,12 @@ func TestDeviceCloning(t *testing.T) {
209225

210226
func TestConcurrency(t *testing.T) {
211227
assert := assert.New(t)
212-
setup(devicePath)
213-
defer teardown(devicePath)
228+
devicePath := setup(defaultBackingImage)
229+
defer teardown(defaultBackingImage, devicePath)
214230

215-
device2 := devicePath + "-2"
216-
setup(device2)
217-
defer teardown(device2)
231+
backingImage2 := defaultBackingImage + "-2"
232+
device2 := setup(backingImage2)
233+
defer teardown(backingImage2, device2)
218234

219235
mapper := cryptmapper.New(&fakeKMS{})
220236

disk-mapper/internal/test/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ go_test(
99
data = [
1010
"@coreutils//:bin/dd",
1111
"@coreutils//:bin/rm",
12+
"@util-linux//:bin/losetup",
1213
],
1314
env = {
1415
"DD": "$(rlocationpath @coreutils//:bin/dd)",
16+
"LOSETUP": "$(rlocationpath @util-linux//:bin/losetup)",
1517
"RM": "$(rlocationpath @coreutils//:bin/rm)",
1618
},
1719
# keep

disk-mapper/internal/test/integration_test.go

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ package integration
1010

1111
import (
1212
"encoding/json"
13+
"errors"
1314
"flag"
1415
"fmt"
1516
"log/slog"
@@ -31,13 +32,15 @@ import (
3132
)
3233

3334
const (
34-
devicePath = "testDevice"
35+
backingDisk = "testDevice"
3536
mappedDevice = "mappedDevice"
3637
)
3738

39+
var devicePath string
40+
3841
var diskPath = flag.String("disk", "", "Path to the disk to use for the benchmark")
3942

40-
var toolsEnvs = []string{"DD", "RM"}
43+
var toolsEnvs = []string{"DD", "RM", "LOSETUP"}
4144

4245
// addToolsToPATH is used to update the PATH to contain necessary tool binaries for
4346
// coreutils.
@@ -64,11 +67,22 @@ func addToolsToPATH() error {
6467
}
6568

6669
func setup(sizeGB int) error {
67-
return exec.Command("dd", "if=/dev/random", fmt.Sprintf("of=%s", devicePath), "bs=1G", fmt.Sprintf("count=%d", sizeGB)).Run()
70+
if err := exec.Command("dd", "if=/dev/random", fmt.Sprintf("of=%s", backingDisk), "bs=1G", fmt.Sprintf("count=%d", sizeGB)).Run(); err != nil {
71+
return err
72+
}
73+
cmd := exec.Command("losetup", "-f", "--show", backingDisk)
74+
out, err := cmd.CombinedOutput()
75+
if err != nil {
76+
return fmt.Errorf("losetup failed: %w\nOutput: %s", err, out)
77+
}
78+
devicePath = strings.TrimSpace(string(out))
79+
return nil
6880
}
6981

7082
func teardown() error {
71-
return exec.Command("rm", "-f", devicePath).Run()
83+
err := exec.Command("losetup", "-d", devicePath).Run()
84+
errors.Join(err, exec.Command("rm", "-f", backingDisk).Run())
85+
return err
7286
}
7387

7488
func TestMain(m *testing.M) {
@@ -137,6 +151,27 @@ func TestMapper(t *testing.T) {
137151
// Disk should still be marked as not initialized because token is set to false.
138152
assert.False(mapper.IsInitialized())
139153

154+
// Set disk as initialized
155+
assert.NoError(ccrypt.SetConstellationStateDiskToken(ccryptsetup.SetDiskInitialized))
156+
157+
// Set up a new client and check if the client still sees the disk as initialized
158+
ccrypt2 := ccryptsetup.New()
159+
freeDevice2, err := ccrypt2.Init(devicePath)
160+
require.NoError(err, "failed to initialize crypt device")
161+
defer freeDevice2()
162+
require.NoError(ccrypt2.LoadLUKS2(), "failed to load LUKS2")
163+
164+
tokenJSON, err = ccrypt2.TokenJSONGet(ccryptsetup.ConstellationStateDiskTokenID)
165+
require.NoError(err, "token should have been set")
166+
var token2 struct {
167+
Type string `json:"type"`
168+
Keyslots []string `json:"keyslots"`
169+
DiskIsInitialized bool `json:"diskIsInitialized"`
170+
}
171+
require.NoError(json.Unmarshal([]byte(tokenJSON), &token2))
172+
assert.True(token2.DiskIsInitialized, "disk should be marked as initialized")
173+
assert.True(ccrypt2.ConstellationStateDiskTokenIsInitialized(), "disk should be marked as initialized")
174+
140175
// Try to map disk with incorrect passphrase
141176
assert.Error(mapper.MapDisk(mappedDevice, "invalid-passphrase"), "was able to map disk with incorrect passphrase")
142177

go.mod

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ module github.com/edgelesssys/constellation/v2
22

33
go 1.24.6
44

5-
// TODO(daniel-weisse): revert after merging https://github.com/martinjungblut/go-cryptsetup/pull/16.
6-
replace github.com/martinjungblut/go-cryptsetup => github.com/daniel-weisse/go-cryptsetup v0.0.0-20230705150314-d8c07bd1723c
5+
replace github.com/martinjungblut/go-cryptsetup => github.com/edgelesssys/go-cryptsetup v0.0.0-20250822075033-840d240dddf8
76

87
// TODO(daniel-weisse): revert after merging https://github.com/google/go-sev-guest/pull/173.
98
replace github.com/google/go-sev-guest => github.com/daniel-weisse/go-sev-guest v0.0.0-20250728114912-0c2ba277c52b

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,6 @@ github.com/cyberphone/json-canonicalization v0.0.0-20220623050100-57a0ce2678a7 h
237237
github.com/cyberphone/json-canonicalization v0.0.0-20220623050100-57a0ce2678a7/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw=
238238
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
239239
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
240-
github.com/daniel-weisse/go-cryptsetup v0.0.0-20230705150314-d8c07bd1723c h1:ToajP6trZoiqlZ3Z4uoG1P02/wtqSw1AcowOXOYjATk=
241-
github.com/daniel-weisse/go-cryptsetup v0.0.0-20230705150314-d8c07bd1723c/go.mod h1:gZoZ0+POlM1ge/VUxWpMmZVNPzzMJ7l436CgkQ5+qzU=
242240
github.com/daniel-weisse/go-sev-guest v0.0.0-20250728114912-0c2ba277c52b h1:pElX9BS0PnYZS/tznradDYbo82kvG2yisWGvZGsDnVs=
243241
github.com/daniel-weisse/go-sev-guest v0.0.0-20250728114912-0c2ba277c52b/go.mod h1:SK9vW+uyfuzYdVN0m8BShL3OQCtXZe/JPF7ZkpD3760=
244242
github.com/danieljoos/wincred v1.2.1 h1:dl9cBrupW8+r5250DYkYxocLeZ1Y4vB1kxgtjxw8GQs=
@@ -271,6 +269,8 @@ github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU
271269
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
272270
github.com/edgelesssys/go-azguestattestation v0.0.0-20250408071817-8c4457b235ff h1:V6A5kD0+c1Qg4X72Lg+zxhCZk+par436sQdgLvMCBBc=
273271
github.com/edgelesssys/go-azguestattestation v0.0.0-20250408071817-8c4457b235ff/go.mod h1:Lz4QaomI4wU2YbatD4/W7vatW2Q35tnkoJezB1clscc=
272+
github.com/edgelesssys/go-cryptsetup v0.0.0-20250822075033-840d240dddf8 h1:aZsuG/e0UNZSttE63TplTeTpYjpl8A2GXbNQYMRUktw=
273+
github.com/edgelesssys/go-cryptsetup v0.0.0-20250822075033-840d240dddf8/go.mod h1:gZoZ0+POlM1ge/VUxWpMmZVNPzzMJ7l436CgkQ5+qzU=
274274
github.com/edgelesssys/go-tdx-qpl v0.0.0-20250129202750-607ac61e2377 h1:5JMJiBhvOUUR7EZ0UyeSy7a1WrqB2eM+DX3odLSHAh4=
275275
github.com/edgelesssys/go-tdx-qpl v0.0.0-20250129202750-607ac61e2377/go.mod h1:IC72qyykUIWl0ZmSk53L4xbLCFDBEGZVaujUmPQOEyw=
276276
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=

internal/cryptsetup/BUILD.bazel

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,14 @@ go_library(
1616
visibility = ["//:__subpackages__"],
1717
deps = select({
1818
"@io_bazel_rules_go//go/platform:android": [
19+
"@com_github_google_uuid//:uuid",
1920
"@com_github_martinjungblut_go_cryptsetup//:go-cryptsetup",
21+
"@org_golang_x_sys//unix",
2022
],
2123
"@io_bazel_rules_go//go/platform:linux": [
24+
"@com_github_google_uuid//:uuid",
2225
"@com_github_martinjungblut_go_cryptsetup//:go-cryptsetup",
26+
"@org_golang_x_sys//unix",
2327
],
2428
"//conditions:default": [],
2529
}),

0 commit comments

Comments
 (0)