Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add S390x Cex base disk encryption #1820

Merged
merged 1 commit into from
May 13, 2024
Merged

Conversation

madhu-pillai
Copy link
Contributor

This PR is to enable CEX mode disk encryption for root volume.

The discussion on this feature has been updated in #1693)

During the unit test , the translation get failed.

@madhu-pillai madhu-pillai marked this pull request as ready for review February 29, 2024 09:43
config/doc/ignition.yaml Outdated Show resolved Hide resolved
config/doc/ignition.yaml Outdated Show resolved Hide resolved
config/doc/ignition.yaml Outdated Show resolved Hide resolved
config/doc/ignition.yaml Outdated Show resolved Hide resolved
config/doc/ignition.yaml Outdated Show resolved Hide resolved
// args manually by verifying the keysize and keytype.
func zkeySecCryptGenArg(luks types.Luks) []string {
ret := []string{
"--master-key-file",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like that name is deprecated and it's now --volume-key-file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed.

func zkeySecCryptGenArg(luks types.Luks) []string {
ret := []string{
"--master-key-file",
"/etc/zkey/repository/root_xts.skey",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll need to adjust this accordingly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed..

Comment on lines 630 to 689
if !util.NilOrEmpty(luks.Cexmode.Keytype) && *luks.Cexmode.Keytype == "CCA-AESDATA" {
ret = append(ret, "--key-size", "1024")
} else {
ret = append(ret, "--key-size", "2176")
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I understand correctly that this arg doesn't actually control the key size since we're explicitly passing in the volume key file to use, but that it's just for checking its size?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as i understand , the cryptsetup wants --key-size when we use the --volume-key-file in xts mode. if we do not provide key size the cryptsetup somehow use default 2*256 bits from the file while formatting the disk and set the key size to 512bits (64bytes).

Without --key-size somehow it wont do the protected key mechanism with CEX card and no longer protected; The volume can be open with passkey without CEX card . Also The zkey validation will fail as well as it fails to set the verification pattern in the Token.

zkey-cryptsetup: # Device /dev/dasdb1 READ lock released.

zkey-cryptsetup: # PBKDF pbkdf2-sha256, time_ms 2000 (iterations 0).

zkey-cryptsetup: # PBKDF pbkdf2-sha256, time_ms 2000 (iterations 0).

zkey-cryptsetup: Installing SIGINT/SIGTERM handler
zkey-cryptsetup: Volume key size: 64
zkey-cryptsetup: Integrity: 'none'
zkey-cryptsetup: Integrity key size: 0
zkey-cryptsetup: The volume key size 64 is not valid for the cipher mode 'xts-plain64'
zkey-cryptsetup: # Releasing crypt device /dev/dasdb1 context.

zkey-cryptsetup: # Releasing device-mapper backend.

zkey-cryptsetup: # Closing read only fd for /dev/dasdb1.

eg:
I tried in one of the OCP worker node by formatting the disk as per the --key-size and the cryptsetup luksDump show the key size exactly as the key-size we provided.

sh-5.1# cryptsetup luksFormat /dev/dasdb1 --pbkdf pbkdf2 --volume-key-file '/etc/zkey/repository/secure_AESCipherKey4.skey' --key-size 2176 --cipher paes-xts-plain64 
WARNING: Device /dev/dasdb1 already contains a 'crypto_LUKS' superblock signature.

WARNING!
========
This will overwrite data on /dev/dasdb1 irrevocably.

Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for /dev/dasdb1: 
Verify passphrase: 
sh-5.1# cryptsetup luksDump /dev/dasdb1
LUKS header information
Version:       	2
Epoch:         	3
Metadata area: 	16384 [bytes]
Keyslots area: 	16744448 [bytes]
UUID:          	62910b38-1e69-4ed0-9e13-b641c423d0a0
Label:         	(no label)
Subsystem:     	(no subsystem)
Flags:       	(no flags)

Data segments:
  0: crypt
	offset: 16777216 [bytes]
	length: (whole device)
	cipher: paes-xts-plain64
	sector: 4096 [bytes]

Keyslots:
  0: luks2
	Key:        2176 bits
	Priority:   normal
	Cipher:     aes-xts-plain64
	Cipher key: 512 bits
	PBKDF:      pbkdf2
	Hash:       sha256
	Iterations: 1865792
	Salt:       cf ac 97 b8 49 92 cf 53 33 85 7e 7c 5e b1 bc 48 
	            5d 1a 3d f9 39 46 16 b8 3c 7f 84 7d 72 e7 64 78 
	AF stripes: 4000
	AF hash:    sha256
	Area offset:32768 [bytes]
	Area length:1089536 [bytes]
	Digest ID:  0

However we do not provide the --key-size here is the output.

sh-5.1# cryptsetup luksFormat /dev/dasdb1 --pbkdf pbkdf2 --volume-key-file '/etc/zkey/repository/secure_AESCipherKey5.skey'  --cipher paes-xts-plain64 
WARNING: Device /dev/dasdb1 already contains a 'crypto_LUKS' superblock signature.

WARNING!
========
This will overwrite data on /dev/dasdb1 irrevocably.

Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for /dev/dasdb1: 
Verify passphrase: 
sh-5.1# cryptsetup luksDump /dev/dasdb1
LUKS header information
Version:       	2
Epoch:         	3
Metadata area: 	16384 [bytes]
Keyslots area: 	16744448 [bytes]
UUID:          	473b0977-45ff-4194-8b53-36dc4babdca1
Label:         	(no label)
Subsystem:     	(no subsystem)
Flags:       	(no flags)

Data segments:
  0: crypt
	offset: 16777216 [bytes]
	length: (whole device)
	cipher: paes-xts-plain64
	sector: 4096 [bytes]

Keyslots:
  0: luks2
	Key:        512 bits
	Priority:   normal
	Cipher:     aes-xts-plain64
	Cipher key: 512 bits
	PBKDF:      pbkdf2
	Hash:       sha256
	Iterations: 1804776
	Salt:       f0 d2 15 e9 06 ad e6 7b a8 3b 28 38 7f 0b cb 99 
	            1e 65 4f 49 58 2d 63 67 3a 5f 1e 2e 2d e6 d0 b3 
	AF stripes: 4000
	AF hash:    sha256
	Area offset:32768 [bytes]
	Area length:258048 [bytes]
	Digest ID:  0

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jlebon adding on above ^ , I had word with zcrypto team. Here is the explanation for that.

If you pass a key to paes that is a valid clear key size, then it uses it as clear key.
So in your case it reads the first 64 bytes from the secure key file and uses them as clear key value for AES-XTS. And for this it of course does not need any crypto cards.
The reason why this is done that way, is because all kernel ciphers need to run a selftest when they are loaded, and this self test can only be performed with clear keys. So paes must also accept clear key as key. Valid secure keys will never have a size that matches a valid clear key size.
So you must be careful and always specify the correct key size during luksFormat.

So the key-size must be verified and use that size as --key-size for luksFormat,
So in the ignition we could read the secure key file-size which guarantees the key-size.
Kindly suggest.

Copy link
Member

@jlebon jlebon Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha, thanks. That clears it up nicely.

I think one confusing thing here is that we're hardcoding key lengths instead of using the source of truth, which is the key that zkey generate generated. Isn't it just the size of the key file itself?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is the size of the key file. The following is key-type CCA-AESCIPHER which generates 272bytes size. CCA-AESDATA generates 128bytes size. Usual cases zkey command manages all argument including the luksFormat and verification. However zkey generates the command arg pbdkf algo as argon2i where FIPS does not support.

sh-5.1# cd /etc/zkey/repository/
sh-5.1# ls
secure_AESCipherKey5.info  secure_AESCipherKey5.skey
sh-5.1# ls -l
total 8
-rw-r-----. 1 root zkeyadm 321 Mar  5 04:26 secure_AESCipherKey5.info
-rw-r-----. 1 root zkeyadm 272 Mar  5 04:26 secure_AESCipherKey5.skey
sh-5.1# KEYBITSIZE=$(stat --printf="%s" secure_AESCipherKey5.skey)
sh-5.1# KEYBITSIZE=$((${KEYBITSIZE}*8))
sh-5.1# echo $KEYBITSIZE
2176

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then I'd say instead of hardcoding these values, let's just os.Stat the keyfile and use its length (* 8) as the argument.

internal/exec/stages/disks/luks.go Outdated Show resolved Hide resolved
internal/exec/stages/disks/luks.go Outdated Show resolved Hide resolved
@jlebon
Copy link
Member

jlebon commented Mar 5, 2024

What's the plan around CI testing this BTW on the CoreOS side? Do we have the required hardware in our pipeline s390x builders to make use of this? Ideally we have a kola test exercising this.

@madhu-pillai
Copy link
Contributor Author

What's the plan around CI testing this BTW on the CoreOS side? Do we have the required hardware in our pipeline s390x builders to make use of this? Ideally we have a kola test exercising this.

The s390x comes with CEX cards, I will check whether LPAR has cex card or not.

@madhu-pillai madhu-pillai force-pushed the test_cex branch 2 times, most recently from 62d71da to 98be9e1 Compare March 12, 2024 08:18
@madhu-pillai
Copy link
Contributor Author

Hi @jlebon , The unit test ./test is failing due to the types.Config translation. I tried to add the translate for cex, but the old_types does not have cex for translation. Am i missing any configuration. Kindly suggest.

@prestist
Copy link
Collaborator

Hi @jlebon , The unit test ./test is failing due to the types.Config translation. I tried to add the translate for cex, but the old_types does not have cex for translation. Am i missing any configuration. Kindly suggest.

Could you post your error here ?

@madhu-pillai
Copy link
Contributor Author

madhu-pillai commented Mar 13, 2024

Could you post your error here ?

[root@fedora ignition]# ./test
Checking for license headers...
Using version from git: 98be9e17-dirty
warning: GOPATH set to GOROOT (/root/go) has no effect
Building ignition...
warning: GOPATH set to GOROOT (/root/go) has no effect
Building ignition-validate...
warning: GOPATH set to GOROOT (/root/go) has no effect
warning: GOPATH set to GOROOT (/root/go) has no effect
warning: GOPATH set to GOROOT (/root/go) has no effect
Checking gofix...
warning: GOPATH set to GOROOT (/root/go) has no effect
go fix: warning: no cgo types: exit status 1
go fix: warning: no cgo types: exit status 1
go fix: warning: no cgo types: exit status 1
go fix: warning: no cgo types: exit status 1
go fix: warning: no cgo types: exit status 1
go fix: warning: no cgo types: exit status 1
go fix: warning: no cgo types: exit status 1
go fix: warning: no cgo types: exit status 1
go fix: warning: no cgo types: exit status 1
go fix: warning: no cgo types: exit status 1
go fix: warning: no cgo types: exit status 1
go fix: warning: no cgo types: exit status 1
go fix: warning: no cgo types: exit status 1
go fix: warning: no cgo types: exit status 1
go fix: warning: no cgo types: exit status 1
go fix: warning: no cgo types: exit status 1
Checking gofmt...

Checking govet...
warning: GOPATH set to GOROOT (/root/go) has no effect
Running tests...
warning: GOPATH set to GOROOT (/root/go) has no effect
ok  	github.com/coreos/ignition/v2/config	(cached)	coverage: 17.6% of statements
?   	github.com/coreos/ignition/v2/config/shared	[no test files]
	github.com/coreos/ignition/v2/config/shared/errors		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/config/doc		coverage: 0.0% of statements
ok  	github.com/coreos/ignition/v2/config/merge	(cached)	coverage: 69.3% of statements
	github.com/coreos/ignition/v2/config/shared/parse		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/config/shared/validations		coverage: 0.0% of statements
ok  	github.com/coreos/ignition/v2/config/translate	(cached)	coverage: 45.2% of statements
	github.com/coreos/ignition/v2/config/util		coverage: 0.0% of statements
ok  	github.com/coreos/ignition/v2/config/v3_0	(cached)	coverage: 41.9% of statements
ok  	github.com/coreos/ignition/v2/config/v3_0/types	(cached)	coverage: 52.7% of statements
ok  	github.com/coreos/ignition/v2/config/v3_1	(cached)	coverage: 49.0% of statements
ok  	github.com/coreos/ignition/v2/config/v3_1/translate	(cached)	coverage: 55.7% of statements
ok  	github.com/coreos/ignition/v2/config/v3_1/types	(cached)	coverage: 55.3% of statements
ok  	github.com/coreos/ignition/v2/config/v3_2	(cached)	coverage: 49.0% of statements
ok  	github.com/coreos/ignition/v2/config/v3_2/translate	(cached)	coverage: 55.3% of statements
ok  	github.com/coreos/ignition/v2/config/v3_2/types	(cached)	coverage: 51.1% of statements
ok  	github.com/coreos/ignition/v2/config/v3_3	(cached)	coverage: 49.0% of statements
ok  	github.com/coreos/ignition/v2/config/v3_3/translate	(cached)	coverage: 55.7% of statements
ok  	github.com/coreos/ignition/v2/config/v3_3/types	(cached)	coverage: 53.7% of statements
ok  	github.com/coreos/ignition/v2/config/v3_4	(cached)	coverage: 49.0% of statements
ok  	github.com/coreos/ignition/v2/config/v3_4/translate	(cached)	coverage: 49.5% of statements
ok  	github.com/coreos/ignition/v2/config/v3_4/types	(cached)	coverage: 57.0% of statements
--- FAIL: TestParse (0.00s)
panic: Translator not defined for types.Config to types.Config [recovered]
	panic: Translator not defined for types.Config to types.Config

goroutine 19 [running]:
testing.tRunner.func1.2({0x2dd260, 0xc00023e920})
	/root/go/src/testing/testing.go:1631 +0x2dc
testing.tRunner.func1()
	/root/go/src/testing/testing.go:1634 +0x3ee
panic({0x2dd260, 0xc00023e920})
	/root/go/src/runtime/panic.go:770 +0x11a
github.com/coreos/ignition/v2/config/translate.translator.translate({{0xc000250060, 0x1, 0x1}}, {0x31f4a0, 0xc00020f4a0, 0x199}, {0x31f2a0, 0xc00020f680, 0x199})
	/root/ignition/config/translate/translate.go:142 +0x358
github.com/coreos/ignition/v2/config/translate.translator.Translate({{0xc000250060, 0x1, 0x1}}, {0x2ea620, 0xc00020f4a0}, {0x2e9ae0, 0xc00020f680})
	/root/ignition/config/translate/translate.go:186 +0x1f0
github.com/coreos/ignition/v2/config/v3_5_experimental/translate.Translate({{{{0x0, 0x0, 0x0}, {0x0, {...}, 0x0, {...}}}, {0x0, 0x0, {0x0, ...}}, ...}, ...})
	/root/ignition/config/v3_5_experimental/translate/translate.go:33 +0x118
github.com/coreos/ignition/v2/config/v3_5_experimental.ParseCompatibleVersion({0xc00012ca50, 0x22, 0x22})
	/root/ignition/config/v3_5_experimental/config.go:77 +0x1ee
github.com/coreos/ignition/v2/config/v3_5_experimental.TestParse(0xc00016ab60)
	/root/ignition/config/v3_5_experimental/config_test.go:217 +0x168e
testing.tRunner(0xc00016ab60, 0x367588)
	/root/go/src/testing/testing.go:1689 +0x14a
created by testing.(*T).Run in goroutine 1
	/root/go/src/testing/testing.go:1742 +0x47c
FAIL	github.com/coreos/ignition/v2/config/v3_5_experimental	0.013s
--- FAIL: TestTranslate (0.00s)
panic: Translator not defined for types.Config to types.Config [recovered]
	panic: Translator not defined for types.Config to types.Config

goroutine 6 [running]:
testing.tRunner.func1.2({0x248360, 0xc000024980})
	/root/go/src/testing/testing.go:1631 +0x2dc
testing.tRunner.func1()
	/root/go/src/testing/testing.go:1634 +0x3ee
panic({0x248360, 0xc000024980})
	/root/go/src/runtime/panic.go:770 +0x11a
github.com/coreos/ignition/v2/config/translate.translator.translate({{0xc00000e570, 0x1, 0x1}}, {0x27ac40, 0xc00017c3c0, 0x199}, {0x27ae40, 0xc00017c5a0, 0x199})
	/root/ignition/config/translate/translate.go:142 +0x358
github.com/coreos/ignition/v2/config/translate.translator.Translate({{0xc00000e570, 0x1, 0x1}}, {0x252840, 0xc00017c3c0}, {0x252e40, 0xc00017c5a0})
	/root/ignition/config/translate/translate.go:186 +0x1f0
github.com/coreos/ignition/v2/config/v3_5_experimental/translate.Translate({{{{0xc00007ac90, 0x1, 0x1}, {0xc000024590, {...}, 0xc0000245b0, {...}}}, {0xc0000245d0, 0xc0000245e0, {0xc0000245f0, ...}}, ...}, ...})
	/root/ignition/config/v3_5_experimental/translate/translate.go:33 +0x142
github.com/coreos/ignition/v2/config/v3_5_experimental/translate.TestTranslate(0xc00013e680)
	/root/ignition/config/v3_5_experimental/translate/translate_test.go:31 +0xfe
testing.tRunner(0xc00013e680, 0x2bbea8)
	/root/go/src/testing/testing.go:1689 +0x14a
created by testing.(*T).Run in goroutine 1
	/root/go/src/testing/testing.go:1742 +0x47c
FAIL	github.com/coreos/ignition/v2/config/v3_5_experimental/translate	0.015s
ok  	github.com/coreos/ignition/v2/config/v3_5_experimental/types	(cached)	coverage: 56.9% of statements
ok  	github.com/coreos/ignition/v2/config/validate	(cached)	coverage: 46.8% of statements
	github.com/coreos/ignition/v2/internal/distro		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/apply		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/as_user		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/earlyrand		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/exec/stages		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/doc		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/exec		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/exec/stages/disks		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/exec/stages/fetch		coverage: 0.0% of statements
ok  	github.com/coreos/ignition/v2/internal/exec/stages/fetch_offline	(cached)	coverage: 12.3% of statements
ok  	github.com/coreos/ignition/v2/internal/exec/stages/files	(cached)	coverage: 1.8% of statements
	github.com/coreos/ignition/v2/internal/exec/stages/kargs		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/exec/stages/mount		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/exec/stages/umount		coverage: 0.0% of statements
ok  	github.com/coreos/ignition/v2/internal/exec/util	(cached)	coverage: 2.1% of statements
?   	github.com/coreos/ignition/v2/internal/providers	[no test files]
	github.com/coreos/ignition/v2/internal/log		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/aws		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/azure		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/azurestack		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/platform		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/cmdline		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/aliyun		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/digitalocean		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/cloudstack		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/applehv		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/exoscale		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/file		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/ibmcloud		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/hetzner		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/hyperv		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/gcp		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/kubevirt		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/nutanix		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/metal		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/packet		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/powervs		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/scaleway		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/openstack		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/qemu		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/virtualbox		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/system		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/util		coverage: 0.0% of statements
ok  	github.com/coreos/ignition/v2/internal/providers/vmware	(cached)	coverage: 13.3% of statements
?   	github.com/coreos/ignition/v2/internal/register	[no test files]
	github.com/coreos/ignition/v2/internal/providers/zvm		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/providers/vultr		coverage: 0.0% of statements
ok  	github.com/coreos/ignition/v2/internal/registry	(cached)	coverage: 90.0% of statements
ok  	github.com/coreos/ignition/v2/internal/resource	(cached)	coverage: 11.1% of statements
	github.com/coreos/ignition/v2/internal/systemd		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/sgdisk		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/state		coverage: 0.0% of statements
ok  	github.com/coreos/ignition/v2/internal/util	(cached)	coverage: 14.7% of statements
?   	github.com/coreos/ignition/v2/internal/version	[no test files]
	github.com/coreos/ignition/v2/validate		coverage: 0.0% of statements
	github.com/coreos/ignition/v2/internal/util/tools/docs		coverage: 0.0% of statements
FAIL

@madhu-pillai
Copy link
Contributor Author

madhu-pillai commented Mar 14, 2024

Hi, Kindly help here.
I tried to add the translation for the v3_5_experimental and add the following. One thing i do not understand is when we translate from old.types to types.<object> it says undefined: old_types.Cex because old_types does not have Cex object ie v3_4/types. Is there any other way to translate?

Did i miss anything here? I read the development doc and it says to add the translation if requires. The error logs as above.

import (
	"github.com/coreos/ignition/v2/config/translate"
	old_types "github.com/coreos/ignition/v2/config/v3_4/types"
	"github.com/coreos/ignition/v2/config/v3_5_experimental/types"
)
 translate code here ..............


++add
func translateLuks(old old_types.Luks) (ret types.Luks) {
	tr := translate.NewTranslator()
	tr.AddCustomTranslator(translateCex)
	tr.Translate(&old.Device, &ret.Device)
	tr.Translate(&old.Label, &ret.Label)
	tr.Translate(&old.Name, &ret.Name)
	tr.Translate(&old.Options, &ret.Options)
	tr.Translate(&old.UUID, &ret.UUID)
	tr.Translate(&old.WipeVolume, &ret.WipeVolume)
	return
}

func translateCex(old old_types.Cex) (ret types.Cex) {
	tr := translate.NewTranslator()
	tr.Translate(&old.KeyType, &ret.KeyType)
	tr.Translate(&old.Enabled, &ret.Enabled)
	return
}

### Bug fixes

## Ignition 2.18.0 (2024-03-01)
## Upcoming Ignition 2.18.0 (unreleased)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks weird...

Copy link
Collaborator

@prestist prestist Apr 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might have a merge conflict that was resolved wrong?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix that..

@@ -0,0 +1 @@
This is a dummy "keyfile" which explain the purpose of this file in the dracut module. A key used to encrypt and decrypt the user data on a volume formatted in luks2 format. A key slot in luks2 header stores a wrapped copy of this volume key, where the wrapping key is derived from the users passphrase or "keyfile". In the infrastructure for protected volume encryption, the luks2 volume key is secure key. The effective volume is twofold protected: it is encrypted by an AES master key from a CCA or EP11 coProcessor and by a wrapping key or KEK derived from a passphrase or "keyfile". Therefore to unlock a luks2 volume a passphrase - provided interactively or from a "keyfile" is required to decrypt the outer wrapping. The security provided by the passphrase or "keyfile" is typically much lower than that provided by the wrapping AES master key. Therefore the password or "keyfile" may be exposed without any loss of security. When a secure key for the PAES cipher is provide to dm-crypt inorder to open a volume, it automatically transforms this secure key into a protected key that can be interpreted by the CPACF. The actual effective key of the luks2 volume key is never exposed to the operating system.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add any formatting for easier consumption?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure,

@@ -112,5 +114,8 @@ installkernel() {
instmods -c vsock
instmods -c vmw_vsock_virtio_transport_common
instmods -c vmw_vsock_virtio_transport

# required for cex card early initialization.
Copy link
Collaborator

@prestist prestist Apr 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove '.' for consistency with other comments similar to this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do

inst_multiple -o chccwdev vmur
inst_multiple -o chccwdev vmur zkey zkey-cryptsetup

inst_simple "$moddir/ignition-cex" "/etc/luks/cex.key"

# Required on system using SELinux
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a '.' for consistency.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do

vmurCmd = "vmur"
chccwdevCmd = "chccwdev"
cioIgnoreCmd = "cio_ignore"
// zVM programs
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

z/VM

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do

@@ -531,3 +566,135 @@ func (d LuksDump) hasFlag(flag string) bool {
}
return false
}

// collect the cex card domains xx.xxxx,
func getAllCexOnlineApqns() (string, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is Apqns an acronym? if so can we cap it i.e APQNS

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it stands for Adjunct Processor Queue Number. An APQN designates the combination of a cryptographic coprocessor (adapter) and a domain. I'll change to Caps.

@@ -531,3 +566,135 @@ func (d LuksDump) hasFlag(flag string) bool {
}
return false
}

// collect the cex card domains xx.xxxx,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

er, is the ',' part of the format?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if not remove ','

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry its err. Removed.

// match the regexp for pattern xx.xxxx
for _, dir := range event {
match := cexRegx.FindStringSubmatch(dir.Name())
// if the match found read the uevent from that apqn directory
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be correct to say

// If a match is found, read the uevent from that APQN directory
// to verify whether it corresponds to a CCA controller. This is 
// intended for potential future use with an EP11 controller.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do that

@madhu-pillai madhu-pillai force-pushed the test_cex branch 2 times, most recently from fd1446d to ce262c2 Compare April 24, 2024 04:39
@madhu-pillai
Copy link
Contributor Author

Hi,
Kindly review the PR. I've updated all the earlier review remarks.

@prestist
Copy link
Collaborator

@madhu-pillai Looks like you still have some failing CI, have you had a chance to look at it ?

@madhu-pillai
Copy link
Contributor Author

madhu-pillai commented Apr 30, 2024

Hi @prestist ,
I've checked the failing test. There are two test get failed in x86 i think. when i run the test manually in my s390x it pass.

  1. ext.config.root-reprovision.luks and luks.autosave.xfs.
    both pointing to the allow_discard missing arguments. Not sure how these tests are related to cex volume encryption.
Apr 24 05:46:16 qemu0 kola-runext-test.sh[2813]: ++ ok 'root mounted with prjquota'
Apr 24 05:46:16 qemu0 kola-runext-test.sh[2813]: ++ echo ok 'root mounted with prjquota'
Apr 24 05:46:16 qemu0 kola-runext-test.sh[2813]: ok root mounted with prjquota
Apr 24 05:46:16 qemu0 kola-runext-test.sh[2819]: +++ dmsetup table myluksdev
Apr 24 05:46:16 qemu0 kola-runext-test.sh[2813]: ++ table='0 19888095 crypt aes-xts-plain64 :64:logon:cryptsetup:ed957e6d-7623-4a98-b550-9b9cca20d3a1-d0 0 252:4 32768'
Apr 24 05:46:16 qemu0 kola-runext-test.sh[2813]: ++ grep -q allow_discards
Apr 24 05:46:16 qemu0 kola-runext-test.sh[2813]: ++ fatal 'missing allow_discards in root DM table: 0 19888095 crypt aes-xts-plain64 :64:logon:cryptsetup:ed957e6d-7623-4a98-b550-9b9cca20d3a1-d0 0 252:4 32768'
Apr 24 05:46:16 qemu0 kola-runext-test.sh[2813]: ++ echo 'missing allow_discards in root DM table: 0 19888095 crypt aes-xts-plain64 :64:logon:cryptsetup:ed957e6d-7623-4a98-b550-9b9cca20d3a1-d0 0 252:4 32768'
Apr 24 05:46:16 qemu0 kola-runext-test.sh[2813]: missing allow_discards in root DM table: 0 19888095 crypt aes-xts-plain64 :64:logon:cryptsetup:ed957e6d-7623-4a98-b550-9b9cca20d3a1-d0 0 252:4 32768
Apr 24 05:46:16 qemu0 kola-runext-test.sh[2813]: ++ exit 1
[cex@linux rhcos]$ cosa list
COREOS_ASSEMBLER_ADD_CERTS=y
----
The COSA container image is more that a week old and likely outdated.
You should pull the latest version with:
podman pull quay.io/coreos-assembler/coreos-assembler:latest
----
+ podman run --rm -ti --security-opt=label=disable --privileged --uidmap=1000:0:1 --uidmap=0:1:1000 --uidmap=1001:1001:64536 -v=/home/cex/rhcos:/srv/ --device=/dev/kvm --device=/dev/fuse --tmpfs=/tmp -v=/var/tmp:/var/tmp --name=cosa -v=/etc/pki/ca-trust:/etc/pki/ca-trust:ro quay.io/coreos-assembler/coreos-assembler:latest list
416.94.202404271533-0
   Timestamp: 2024-04-27T15:37:39Z (3 days, 2:49:46 ago)
   Artifacts: ostree oci-manifest qemu metal metal4k live-iso live-kernel live-initramfs live-rootfs
      Config: master (59526550b3a4) (dirty)

+ rc=0
+ set +x
[cex@linux rhcos]$ cosa kola run ext.config.shared.root-reprovision.autosave-xfs
COREOS_ASSEMBLER_ADD_CERTS=y
----
The COSA container image is more that a week old and likely outdated.
You should pull the latest version with:
podman pull quay.io/coreos-assembler/coreos-assembler:latest
----
+ podman run --rm -ti --security-opt=label=disable --privileged --uidmap=1000:0:1 --uidmap=0:1:1000 --uidmap=1001:1001:64536 -v=/home/cex/rhcos:/srv/ --device=/dev/kvm --device=/dev/fuse --tmpfs=/tmp -v=/var/tmp:/var/tmp --name=cosa -v=/etc/pki/ca-trust:/etc/pki/ca-trust:ro quay.io/coreos-assembler/coreos-assembler:latest kola run ext.config.shared.root-reprovision.autosave-xfs
kola -p qemu run ext.config.shared.root-reprovision.autosave-xfs --output-dir tmp/kola
⏰ Snooze for kola test pattern "basic" expired on Apr 01 2024
  👉 https://github.com/openshift/os/issues/1237
⏰ Snooze for kola test pattern "iso-live-login.uefi-secure" expired on Apr 01 2024
  👉 https://github.com/openshift/os/issues/1237
⏰ Snooze for kola test pattern "iso-as-disk.uefi-secure" expired on Apr 01 2024
  👉 https://github.com/openshift/os/issues/1237
⏰ Snooze for kola test pattern "ext.config.rpm-ostree.replace-rt-kernel" expired on Apr 01 2024
  👉 https://github.com/openshift/os/issues/1383
⏰ Snooze for kola test pattern "ext.config.shared.content-origins" expired on Apr 01 2024
  👉 https://github.com/openshift/os/issues/1387#issuecomment-1769313807
⏰ Snooze for kola test pattern "ext.config.version.rhel-matches-rhcos-build" expired on Apr 01 2024
  👉 https://github.com/openshift/os/issues/1387#issuecomment-1769313807
⏭️  Skipping kola test pattern "iso-offline-install-iscsi.bios":
  👉 https://github.com/coreos/fedora-coreos-tracker/issues/1638
=== RUN   ext.config.shared.root-reprovision.autosave-xfs
--- PASS: ext.config.shared.root-reprovision.autosave-xfs (91.39s)
PASS, output in tmp/kola
+ rc=0
+ set +x

@madhu-pillai
Copy link
Contributor Author

Hi,
i need a help here.
The test did the luks format on the volume. But later the test cannot find --allow-discards from the dmsetup table . Earlier i could not test it because i do not have x86 system. Now I setup a x86 vm and run the test.
I did not touch anything in the filesystem area.
All i can see is the VScode IDE undefined execUtil.FileSystemInfo and execUtil.GetFileSystemInfo in luks.go and filesystems.go . i cloned from main branch and again checked it shows similar issue.

@madhu-pillai
Copy link
Contributor Author

Resolved the earlier failed test. Kindly review.

Copy link
Member

@jlebon jlebon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is looking good overall, just lots of minor comments.

Can we follow up on

What's the plan around CI testing this BTW on the CoreOS side? Do we have the required hardware in our pipeline s390x builders to make use of this? Ideally we have a kola test exercising this.

The s390x comes with CEX cards, I will check whether LPAR has cex card or not.

?

We need to scope in a kola test as part of this feature work.

config/doc/ignition.yaml Outdated Show resolved Hide resolved
config/doc/ignition.yaml Outdated Show resolved Hide resolved
- name: enabled
desc: whether or not to use a CEX secure key to encrypt luks device.
- name: keyType
desc: the type of the secure key (CCA-AESDATA or CCA-AESCIPHER). Defaults to CCA-AESCIPHER.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On this topic and following up on #1693 (comment), is there a reason one would want CCA-AESDATA? Trying to reduce config knobs that aren't necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason for the optional key-type as below.
By default if we do not give --key-type it uses CCA-AESDATA .

`CCA-AESDATA` -> support Linux upstream kernel version 4.12 or later use with  < CEX6C model card
`CCA-AESCIPHER` -> support Linux upstream kernel version 5.14 (or older version where required modules  have been backported)

The different secure key types have different sizes (in bytes):

• CCA AES DATA: 64, 128 for XTS
• CCA AES CIPHER: 136, 272 for XTS 
• EP11 AES: 320, 640 for XTS

According to IBM allow an option to select key-type variant.

  1. AES CIPHER keys can be presented as default & recommended
  2. AES DATA keys are less secure and should only be used if at one point in time an export of those keys will be required. AES CIPHER does not support export of keys.

In terms of Config knob cex: true is prettiest and easy. But I think we need to provide an option to user to choose the key-type.

Kindly suggest.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I think we need to provide an option to user to choose the key-type.

Do we? I can imagine some situations where a user could want to export the volume key (e.g. for backup or migration), but I'm not sure how desirable they are in practice vs just reprovisioning the node since Ignition is usually used in situations where that's the preferred option. Important data is usually backed up at the userspace/filesystem level instead (or e.g. mounted from dedicated storage services). ISTM like a large part of the appeal with CEX is that the keys never leave the hardware.

We could also not support it to start and see if there's strong motivation to add support for it in the future. It wouldn't be hard to add it at that point. I would still structure it as

cex:
  enabled: true

for extending it for this and anything else in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understood, Will remove keyType option.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

docs/release-notes.md Outdated Show resolved Hide resolved
if util.NilOrEmpty(luks.KeyFile.Source) {

if luks.Cex.IsPresent() {
keyFilePath = "/etc/luks/cex.key"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One note on this is that if multiple LUKS devices are encrypted via CEX secure keys, we're going to have a copy of this file in /etc/luks/ for each LUKS device. Not a big deal, and I don't think it's worth trying to complicate things to special-case it further, but just noting.

Maybe let's make a comment about that here?

Copy link
Contributor Author

@madhu-pillai madhu-pillai May 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If i understood correctly.

One note on this is that if multiple LUKS devices are encrypted via CEX secure keys, we're going to have a copy of this file in /etc/luks/ for each LUKS device

No, Only one file for all devices, as these are --key-file for the cryptsetup to create and open. I think it overwrites for each devices. If i am not wrong.?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh Sorry, I mis understood.. Yes each device name it creates new file....

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a comment about this as suggested?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

internal/exec/stages/disks/luks.go Show resolved Hide resolved
var (
ErrFilesystemUndefined = errors.New("the referenced filesystem was not defined")
)
var ErrFilesystemUndefined = errors.New("the referenced filesystem was not defined")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor/optional: unrelated change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will correct it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -123,6 +121,11 @@ func (s stage) runImpl(config types.Config, isApply bool, applyIgnoreUnsupported
if err := s.relabelFiles(); err != nil {
return fmt.Errorf("failed to handle relabeling: %v", err)
}

// !isApply: saves LUKS volume key
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd put this right after the createCrypttabEntries() since it's related.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will add next to createCrypttabEntries()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

s.Logger.PushPrefix("createCexVolumeKeys")
defer s.Logger.PopPrefix()
for _, luks := range config.Storage.Luks {
if luks.Cex.IsPresent() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: instead of intending here, I'd reflow as:

if !luks.Cex.IsPresent() {
    continue
}
...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will realign the flow.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

fileExt := []string{".info", ".skey"}
entries := []filesystemEntry{}
for _, zfile := range fileExt {
zkeyFile := filepath.Join(distro.LuksRealVolumeKeyFilePath(), "ignition-luks-"+luks.Name+zfile)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That ignition-luks-"+luks.Name+ext happens enough times in both this file and luks.go` at this point that it probably makes sense to add tiny helpers somewhere that can be shared.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added helper function in util so that it can be shared across on luks.go and filesystementries.go.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@madhu-pillai
Copy link
Contributor Author

I think this is looking good overall, just lots of minor comments.

Can we follow up on

What's the plan around CI testing this BTW on the CoreOS side? Do we have the required hardware in our pipeline s390x builders to make use of this? Ideally we have a kola test exercising this.

The s390x comes with CEX cards, I will check whether LPAR has cex card or not.

?

We need to scope in a kola test as part of this feature work.

Presently we do not have cex hardware for the CI pipeline test. I had discussion with Holger and for the time we mitigate the issues we are facing by supporting only the part that is currently impletement/working/tested and documented it as such.

@madhu-pillai
Copy link
Contributor Author

I think this is looking good overall, just lots of minor comments.
Can we follow up on

What's the plan around CI testing this BTW on the CoreOS side? Do we have the required hardware in our pipeline s390x builders to make use of this? Ideally we have a kola test exercising this.

The s390x comes with CEX cards, I will check whether LPAR has cex card or not.

?
We need to scope in a kola test as part of this feature work.

Presently we do not have cex hardware for the CI pipeline test. I had discussion with Holger and for the time we mitigate the issues we are facing by supporting only the part that is currently impletement/working/tested and documented it as such.

Is it a viable option like. We have a VM with CEX card and each rhcos build can be test run on that vm; whenever a new rhcos build the cronjob in the VM can sense and trigger a kola cex test?

"ignition-luks-" + luks.Name,
"--xts",
"--description",
"Secure Key for Root Volume",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessarily root. Should probably use luks.Name instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@jlebon
Copy link
Member

jlebon commented May 7, 2024

Is it a viable option like. We have a VM with CEX card and each rhcos build can be test run on that vm; whenever a new rhcos build the cronjob in the VM can sense and trigger a kola cex test?

That could be an option. The best would be if the builders we use can have access to CEX hardware. But otherwise, yes we could also trigger a separate test that e.g. provisions a VM in IBM Cloud (is that where the VM would be?) and runs tests there.

@holgwolf
Copy link

holgwolf commented May 8, 2024

That could be an option. The best would be if the builders we use can have access to CEX hardware. But otherwise, yes we could also trigger a separate test that e.g. provisions a VM in IBM Cloud (is that where the VM would be?) and runs tests there.

having CEX in the cloud is not possible, this is a pure on-prem available feature.
What might be possible as we doing it with existing environments used already for OCP CICD and RHCOS

if util.NilOrEmpty(luks.KeyFile.Source) {

if luks.Cex.IsPresent() {
keyFilePath = "/etc/luks/cex.key"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a comment about this as suggested?

"CCA-AESCIPHER",
"--xts",
"--description",
"Secure Key for " + luks.Name + " Volume.",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Super minor: let's drop the final period here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment Added. and dropped the period. Done

internal/exec/stages/disks/luks.go Outdated Show resolved Hide resolved
internal/exec/stages/disks/luks.go Outdated Show resolved Hide resolved
if luks.Cex.IsPresent() {
err := s.zkeyCryptSetvp(luks, keyFilePath)
if err != nil {
return fmt.Errorf("zkey cryptsetup setvp failed: %w", err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd just return err here since the error context within s.zkeyCryptSetvp() seems sufficient.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

internal/exec/stages/disks/luks.go Outdated Show resolved Hide resolved
internal/exec/stages/disks/luks.go Outdated Show resolved Hide resolved
@@ -131,3 +131,13 @@ func PathExists(path string) (bool, error) {
}
return true, nil
}

// Helper function to concatenate the key files.
func ZKeyHelper(l string) map[string]string {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This really needs a more specific name. E.g. ZkeySecureKeyRepoFiles?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

zkeyfile := execUtil.ZKeyHelper(luks.Name)
zfilePath := distro.LuksRealVolumeKeyFilePath()
for _, zfile := range zkeyfile {
key, err := os.ReadFile(zfilePath + zfile)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should join paths here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -41,6 +41,9 @@ type State struct {
// the filesystem during files stage. This is for special
// circumstances only.
ProviderOutputFiles []types.File `json:"providerOutputFiles"`
// Volume Key files generated during LUKS setup in disks stage, which
// need to be written out during files stage.
LuksPersistVolumeKeyFiles map[string]string `json:"luksPersistVolumeKeyFiles"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor/optional: since this includes both secure keys and info files, we could make this more generic, e.g. LuksPersistSecureKeyRepoFiles?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Member

@jlebon jlebon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks a lot for working through all those rounds of review.

This code went through a lot of revisions; can you confirm that the latest version works well with the latest RHCOS 4.16 builds? Were you able to check both the rootfs and secondary filesystem cases? (I know there's still coreos/fedora-coreos-config#2986 that we need to work on, but apart from that.)

@madhu-pillai
Copy link
Contributor Author

madhu-pillai commented May 12, 2024

LGTM! Thanks a lot for working through all those rounds of review.

This code went through a lot of revisions; can you confirm that the latest version works well with the latest RHCOS 4.16 builds? Were you able to check both the rootfs and secondary filesystem cases? (I know there's still coreos/fedora-coreos-config#2986 that we need to work on, but apart from that.)

Hi @jlebon and @prestist , Thanks a lot for your support.

I performed testing before every PR push on all the platform , zKvm, zVm-zfcp and zVm-eckd.

<style> </style>
CEX Encryption card encryption rhcos-416.94.202405090909 & fedora-coreos-39.20240508 zVM zKVM Remarks
With Live image Tested Ok Tested Ok  
qcow2   Tested Ok  
Reboot test Tested Ok Tested Ok  
Shutdown activate Tested Ok Not able to save the vm state due to cex card  
Added 3  Cards with Same masterkey Tested Ok with Single card Able to boot and reboot
Disabled 2 cards and one active card Tested Ok   Able to boot and reboot
Removed all cards Tested Ok   not able to boot
Tested on virtual device (/dev/vda4)   Tested Ok  
Tested on scsi disk Tested Ok   Able to boot and reboot
Tested on Dasd Tested Ok   Able to boot and reboot. With changes in fedora coreos config
Same build with Tang (without Cex) Tested Ok Tested Ok  

Here is the ignition config i used for testing. For each luks device and disk i changes accordingly. zfcp device: /dev/sda4 eckd device: /dev/dasda2 on kvm device: /dev/disk/by-partlabel/root .

[root@KVM ignition]# cat kvmconfig.ign 
{
  "ignition": {
    "version": "3.5.0-experimental"
  }, 
  "kernelArguments": {
    "shouldExist": [
      "rd.luks.key=/etc/luks/cex.key"
    ]
  },
  "passwd": {
    "users": [
      {
        "name": "core",
        "sshAuthorizedKeys": [
          "ssh-ed25519 AAAAC3C1lZDI1NTE5AAAAIJLw9d5d0DslsllsdfkjlakJGnbTlD6IXu7NX2puMhPor3oTjIOv"
        ]
      }
    ]
  },
  "storage": {
    "disks": [
      {
        "device": "/dev/vda",
        "partitions": [
          {
            "label": "root",
            "number": 4,
            "resize": true,
            "sizeMiB": 0
          }
        ]
      }
    ],
    "files": [
      {
        "path": "/etc/sshd/sshd_config.d/20-enable-passwords.conf",
        "contents": {
          "compression": "",
          "source": "data:,PasswordAuthentication%20yes%0A"
        },
        "mode": 420
      }
    ],
    "filesystems": [
      {
        "device": "/dev/mapper/root",
        "format": "xfs",
        "label": "root",
        "wipeFilesystem": true
      }
    ],
    "luks": [
      {
	"cex": {
		"enabled": true 
	},
        "device": "/dev/disk/by-partlabel/root",
        "label": "luks-root",
        "name": "root",
        "wipeVolume": true
      }
    ]
  }
}

Extend the `luks` schema to support a new `cex` key. When enabled, the
volume key of the LUKS device uses a secure key generated using a CEX
card. The keyfile to unlock the volume is not considered confidential.

Closes: coreos#1693

Co-authored-by: Jonathan Lebon <jonathan@jlebon.com>
@jlebon
Copy link
Member

jlebon commented May 13, 2024

I just added more details to the commit message and marked it as closing #1693.

Auto-merge enabled.

@jlebon jlebon merged commit d98cb12 into coreos:main May 13, 2024
9 checks passed
jlebon added a commit to madhu-pillai/coreos-assembler that referenced this pull request Aug 29, 2024
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 <jonathan@jlebon.com>
jlebon added a commit to coreos/coreos-assembler that referenced this pull request Sep 16, 2024
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 <jonathan@jlebon.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants