Skip to content

Commit 41e5c4a

Browse files
madhu-pillaijlebon
andcommitted
kola: add IBM CEX device test for the s390x build
This kola test is crucial for verifying the security of CEX hardware-based LUKS encryption on root volume. It guarantees that the encrypted device employs protected keys to encrypt and decrypt the volume. This is essentially testing the enablement done in coreos/ignition#1820. To run this, it needs to be on a system with a CEX device with passthrough enabled and the device's UUID exposed via KOLA_CEX_UUID. See also coreos/fedora-coreos-pipeline#1010. Co-authored-by: Jonathan Lebon <[email protected]>
1 parent 0254b86 commit 41e5c4a

File tree

7 files changed

+132
-0
lines changed

7 files changed

+132
-0
lines changed

mantle/cmd/kola/options.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ func init() {
168168
bv(&kola.QEMUOptions.SecureExecution, "qemu-secex", false, "Run IBM Secure Execution Image")
169169
sv(&kola.QEMUOptions.SecureExecutionIgnitionPubKey, "qemu-secex-ignition-pubkey", "", "Path to Ignition GPG Public Key")
170170
sv(&kola.QEMUOptions.SecureExecutionHostKey, "qemu-secex-hostkey", "", "Path to Secure Execution HKD certificate")
171+
// s390x CEX-specific options
172+
bv(&kola.QEMUOptions.Cex, "qemu-cex", false, "Attach CEX device to guest")
171173
}
172174

173175
// Sync up the command line options if there is dependency

mantle/cmd/kola/qemuexec.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,14 @@ func runQemuExec(cmd *cobra.Command, args []string) error {
391391
}
392392
}
393393

394+
// IBM Cex based luks encryption.
395+
if kola.QEMUOptions.Cex {
396+
err := builder.AddCexDevice()
397+
if err != nil {
398+
return err
399+
}
400+
}
401+
394402
if devshell && !devshellConsole {
395403
return runDevShellSSH(ctx, builder, config, sshCommand)
396404
}

mantle/kola/tests/ignition/luks.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ package ignition
22

33
import (
44
"fmt"
5+
"os"
56
"time"
67

78
coreosarch "github.com/coreos/stream-metadata-go/arch"
89

910
"github.com/coreos/coreos-assembler/mantle/kola"
1011
"github.com/coreos/coreos-assembler/mantle/kola/cluster"
1112
"github.com/coreos/coreos-assembler/mantle/kola/register"
13+
"github.com/coreos/coreos-assembler/mantle/kola/tests/coretest"
1214
ut "github.com/coreos/coreos-assembler/mantle/kola/tests/util"
1315
"github.com/coreos/coreos-assembler/mantle/platform"
1416
"github.com/coreos/coreos-assembler/mantle/platform/conf"
@@ -50,6 +52,20 @@ func init() {
5052
ExcludeArchitectures: []string{"s390x"}, // no TPM backend support for s390x
5153
Tags: []string{"luks", "tpm", "tang", "sss", kola.NeedsInternetTag, "reprovision"},
5254
})
55+
register.RegisterTest(&register.Test{
56+
Run: runCexTest,
57+
ClusterSize: 0,
58+
Name: `luks.cex`,
59+
Description: "Verify that CEX-based rootfs encryption works.",
60+
Flags: []register.Flag{},
61+
Platforms: []string{"qemu"},
62+
Architectures: []string{"s390x"},
63+
Tags: []string{"luks", "cex", "reprovision"},
64+
NativeFuncs: map[string]register.NativeFuncWrap{
65+
"RHCOSGrowpart": register.CreateNativeFuncWrap(coretest.TestRHCOSGrowfs, []string{"fcos"}...),
66+
"FCOSGrowpart": register.CreateNativeFuncWrap(coretest.TestFCOSGrowfs, []string{"rhcos"}...),
67+
},
68+
})
5369
}
5470

5571
func setupTangMachine(c cluster.TestCluster) ut.TangServer {
@@ -176,6 +192,74 @@ func runTest(c cluster.TestCluster, tpm2 bool, threshold int, killTangAfterFirst
176192
ut.LUKSSanityTest(c, tangd, m, tpm2, killTangAfterFirstBoot, rootPart)
177193
}
178194

195+
func runCexTest(c cluster.TestCluster) {
196+
var err error
197+
var m platform.Machine
198+
199+
// To prevent the test to fail the whole run on s390x machine that does not have Cex Device
200+
cex_uuid := os.Getenv("KOLA_CEX_UUID")
201+
if cex_uuid == "" {
202+
c.Skip("No CEX device found in KOLA_CEX_UUID env var")
203+
}
204+
205+
ignition := conf.Ignition(`{
206+
"ignition": {
207+
"version": "3.5.0-experimental"
208+
},
209+
"kernelArguments": {
210+
"shouldExist": [
211+
"rd.luks.key=/etc/luks/cex.key"
212+
]
213+
},
214+
"storage": {
215+
"luks": [
216+
{
217+
"name": "root",
218+
"device": "/dev/disk/by-label/root",
219+
"cex": {
220+
"enabled": true
221+
},
222+
"label": "root",
223+
"wipeVolume": true
224+
}
225+
],
226+
"filesystems": [
227+
{
228+
"device": "/dev/mapper/root",
229+
"format": "xfs",
230+
"wipeFilesystem": true,
231+
"label": "root"
232+
}
233+
]
234+
}
235+
}`)
236+
237+
opts := platform.QemuMachineOptions{
238+
Cex: true,
239+
}
240+
opts.MinMemory = 8192
241+
242+
switch pc := c.Cluster.(type) {
243+
case *qemu.Cluster:
244+
m, err = pc.NewMachineWithQemuOptions(ignition, opts)
245+
default:
246+
panic("Unsupported cluster type")
247+
}
248+
249+
// copy over kolet into the machine
250+
if err := kola.ScpKolet([]platform.Machine{m}); err != nil {
251+
c.Fatal(err)
252+
}
253+
coretest.LocalTests(c)
254+
255+
if err != nil {
256+
c.Fatalf("Unable to create test machine: %v", err)
257+
}
258+
rootPart := "/dev/disk/by-partlabel/root"
259+
260+
ut.LUKSSanityCEXTest(c, m, rootPart)
261+
}
262+
179263
// Verify that the rootfs is encrypted with Tang
180264
func luksTangTest(c cluster.TestCluster) {
181265
runTest(c, false, 1, false)

mantle/kola/tests/util/luks.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,21 @@ func LUKSSanityTest(c cluster.TestCluster, tangd TangServer, m platform.Machine,
7979
luksDump = c.MustSSH(m, "sudo cryptsetup luksDump "+rootPart)
8080
mustMatch(c, "Cipher: *aes", luksDump)
8181
}
82+
83+
// LUKSSanityCEXTest verifies that the rootfs is encrypted with Cex based LUKS
84+
func LUKSSanityCEXTest(c cluster.TestCluster, m platform.Machine, rootPart string) {
85+
var err error
86+
luksDump := c.MustSSH(m, "sudo cryptsetup luksDump "+rootPart)
87+
mustMatch(c, "cipher: paes-*", luksDump)
88+
mustNotMatch(c, "Cipher: *cipher_null-ecb", luksDump)
89+
mustMatch(c, "0: paes-verification-pattern", luksDump)
90+
mustNotMatch(c, "9: *coreos", luksDump)
91+
92+
err = m.Reboot()
93+
94+
if err != nil {
95+
c.Fatalf("Failed to reboot the machine: %v", err)
96+
}
97+
luksDump = c.MustSSH(m, "sudo cryptsetup luksDump "+rootPart)
98+
mustMatch(c, "cipher: paes-*", luksDump)
99+
}

mantle/platform/machine/qemu/cluster.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,12 @@ func (qc *Cluster) NewMachineWithQemuOptions(userdata *conf.UserData, options pl
150150
primaryDisk = *diskp
151151
}
152152

153+
if qc.flight.opts.Cex || options.Cex {
154+
if err := builder.AddCexDevice(); err != nil {
155+
return nil, err
156+
}
157+
}
158+
153159
if qc.flight.opts.Nvme || options.Nvme {
154160
primaryDisk.Channel = "nvme"
155161
}

mantle/platform/machine/qemu/flight.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ type Options struct {
5555
SecureExecutionIgnitionPubKey string
5656
SecureExecutionHostKey string
5757

58+
// Option to create IBM cex based luks encryption
59+
Cex bool
60+
5861
*platform.Options
5962
}
6063

mantle/platform/qemu.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ type QemuMachineOptions struct {
7575
OverrideBackingFile string
7676
Firmware string
7777
Nvme bool
78+
Cex bool
7879
}
7980

8081
// QEMUMachine represents a qemu instance.
@@ -2063,3 +2064,13 @@ func (builder *QemuBuilder) Close() {
20632064
os.RemoveAll(builder.tempdir)
20642065
}
20652066
}
2067+
2068+
// supports IBM Cex based LUKS encryption if it is s390x host (zKVM/LPAR)
2069+
func (builder *QemuBuilder) AddCexDevice() error {
2070+
cex_uuid := os.Getenv("KOLA_CEX_UUID")
2071+
if cex_uuid == "" {
2072+
return errors.New("cannot add CEX device: KOLA_CEX_UUID env var undefined")
2073+
}
2074+
builder.Append("-device", fmt.Sprintf("vfio-ap,sysfsdev=/sys/devices/vfio_ap/matrix/%s", cex_uuid))
2075+
return nil
2076+
}

0 commit comments

Comments
 (0)