Feature: implement swtpm in runc
This patch series adds a vTPM support for Linux to libcontainer.
The functionality is based on swtpm_cuse binary to create cuse device on which a TPM emulator listen for TPM commands. If we for example want to create vtpmName device then we make this device available as /dev/tpm + vtpmName inside the container. We also add its major and minor numbers to the device cgroup.
We implement a VTPM class that allows us to create the device and starts a TPM emulator 'swtpm_cuse'. Besides that, the user can choose to have the vTPM create certificates in a step that simulates TPM manufacturing. We do this by calling the external swtpm_setup program, which is a part of the swtpm project.
vTPM support is added inside the JSON configuration as follows:
[...]
"linux": {
"resources": {
"devices": [
{
"allow": false,
"access": "rwm"
}
] ,
"vtpms": [
{
"statePath": "/var/lib/runc/myvtpm1",
"statePathIsManaged": false,
"vtpmVersion": "2",
"createCerts": false,
"runAs": "tss",
"pcrBanks": "sha1,sha512",
"encryptionPassword": "mysecret",
"vtpmName": "tpm0",
"vtpmMajor": 100,
"vtpmMinor": 1
}
]
},
This JSON markup makes a single TPM available inside the created container:
- The statePath parameter indicates the directory where the TPM emulator 'swtpm_cuse' writes the state of the TPM device to.
- The createCerts parameter indicates that certificates for the TPM are to be created.
- The vtpmName parameter indicates that /dev/tpm + vtpmName device will be created under container rootfs.
Users can have a requirement to create 2 containers with separated vTPM devices with the same vtpmName in the container rootfs. In the host the created vTPM will have the devpath like that: /dev/tpm + hash of runc root + "-" + containerName + "-" + vtpmName. vTPM devices require runc to be run by root. If runc is running in non-default user namespace or have user namespace in config, then /dev/tpm + hash of runc root + "-" + containerName + "-" + vtpmName will be passed to the container instead of /dev/tpm + vtpmName.
There are several checks to be sure that vTPM devices are unique and won't miss the state between themselves:
- vtpmName should be unique
- statePath should be unique
- no swtpm_cuse / runc runned with the same statePath
The third check is done by starting 'swtpm_cuse' by checking two file locks on '.runc-lock' and '.lock' in the state dir.
In order to run unit / integration tests in the docker container you should also add vtpmMajor and vtpmMinor parameters to the vTPM spec, add them to the cgroup allow rule and pass /dev/cuse device. This is done because tmpfs is usually mounted on the container's /dev/path that's why the new devices won't be propagated to the test container. Also, swtpm.sh script is added to download swtpm and libtpms source code to the test container and build it. google/go-tpm is added to the dependency list because it is used in tpm-helper binary to check vTPM devices in the integration tests.
This PR is based on the previous PR.
The swtpm project is available here
The libtpms project is available here
A virtual TPM sounds interesting to me. Is there a runtime-spec PR for this already? That will be needed too.
I haven't had a look at the code yet :)
A virtual TPM sounds interesting to me. Is there a runtime-spec PR for this already? That will be needed too.
I haven't had a look at the code yet :)
Hello! Thank you for your interest. There is a link for runtime-spec PR. In order to simplify runc/runtime-spec code changes, we have reconsidered our current approach to pass vTPM devices. We will be grateful if you review it as a runc maintainer.