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 TPM Support #260

Merged
merged 8 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .web-docs/components/builder/clone/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ boot time.

- `rng0` (rng0Config) - Configure Random Number Generator via VirtIO. See [VirtIO RNG device](#virtio-rng-device)

- `tpm_config` (tpmConfig) - Set the tpmstate storage options. See [TPM Config](#tpm-config).

- `vga` (vgaConfig) - The graphics adapter to use. See [VGA Config](#vga-config).

- `network_adapters` ([]NICConfig) - The network adapter to use. See [Network Adapters](#network-adapters)
Expand Down
2 changes: 2 additions & 0 deletions .web-docs/components/builder/iso/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ in the image's Cloud-Init settings for provisioning.

- `rng0` (rng0Config) - Configure Random Number Generator via VirtIO. See [VirtIO RNG device](#virtio-rng-device)

- `tpm_config` (tpmConfig) - Set the tpmstate storage options. See [TPM Config](#tpm-config).

- `vga` (vgaConfig) - The graphics adapter to use. See [VGA Config](#vga-config).

- `network_adapters` ([]NICConfig) - The network adapter to use. See [Network Adapters](#network-adapters)
Expand Down
2 changes: 1 addition & 1 deletion builder/proxmox/clone/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func (*cloneVMCreator) Create(vmRef *proxmoxapi.VmRef, config proxmoxapi.ConfigQ
if err != nil {
return err
}
err = config.UpdateConfig(vmRef, client)
_, err = config.Update(false, vmRef, client)
if err != nil {
return err
}
Expand Down
2 changes: 2 additions & 0 deletions builder/proxmox/clone/config.hcl2spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

71 changes: 70 additions & 1 deletion builder/proxmox/common/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: MPL-2.0

//go:generate packer-sdc struct-markdown
//go:generate packer-sdc mapstructure-to-hcl2 -type Config,NICConfig,diskConfig,rng0Config,pciDeviceConfig,vgaConfig,additionalISOsConfig,efiConfig
//go:generate packer-sdc mapstructure-to-hcl2 -type Config,NICConfig,diskConfig,rng0Config,pciDeviceConfig,vgaConfig,additionalISOsConfig,efiConfig,tpmConfig

package proxmox

Expand Down Expand Up @@ -136,6 +136,8 @@ type Config struct {
Machine string `mapstructure:"machine"`
// Configure Random Number Generator via VirtIO. See [VirtIO RNG device](#virtio-rng-device)
Rng0 rng0Config `mapstructure:"rng0"`
// Set the tpmstate storage options. See [TPM Config](#tpm-config).
TPMConfig tpmConfig `mapstructure:"tpm_config"`
// The graphics adapter to use. See [VGA Config](#vga-config).
VGA vgaConfig `mapstructure:"vga"`
// The network adapter to use. See [Network Adapters](#network-adapters)
Expand Down Expand Up @@ -371,6 +373,35 @@ type efiConfig struct {
EFIType string `mapstructure:"efi_type"`
}

// Set the tpmstate storage options.
//
// HCL2 example:
//
// ```hcl
//
// tpm_config {
// tpm_storage_pool = "local"
mpywell marked this conversation as resolved.
Show resolved Hide resolved
// tpm_version = "v1.2"
// }
//
// ```
// Usage example (JSON):
//
// ```json
//
// "tpm_config": {
// "tpm_storage_pool": "local",
// "tpm_version": "v1.2"
// }
//
// ```
type tpmConfig struct {
// Name of the Proxmox storage pool to store the EFI disk on.
TPMStoragePool string `mapstructure:"tpm_storage_pool"`
// Version of TPM spec. Can be `v1.2` or `v2.0` Defaults to `v2.0`.
Version string `mapstructure:"tpm_version"`
}

// - `rng0` (object): Configure Random Number Generator via VirtIO.
// A virtual hardware-RNG can be used to provide entropy from the host system to a guest VM helping avoid entropy starvation which might cause the guest system slow down.
// The device is sourced from a host device and guest, his use can be limited: `max_bytes` bytes of data will become available on a `period` ms timer.
Expand Down Expand Up @@ -602,6 +633,10 @@ func (c *Config) Prepare(upper interface{}, raws ...interface{}) ([]string, []st
log.Printf("OS not set, using default 'other'")
c.OS = "other"
}
ideCount := 0
sataCount := 0
scsiCount := 0
virtIOCount := 0
for idx, disk := range c.Disks {
if disk.Type == "" {
log.Printf("Disk %d type not set, using default 'scsi'", idx)
Expand Down Expand Up @@ -635,6 +670,28 @@ func (c *Config) Prepare(upper interface{}, raws ...interface{}) ([]string, []st
if disk.StoragePoolType != "" {
warnings = append(warnings, "storage_pool_type is deprecated and should be omitted, it will be removed in a later version of the proxmox plugin")
}
switch disk.Type {
case "ide":
ideCount++
case "sata":
sataCount++
case "scsi":
scsiCount++
case "virtio":
virtIOCount++
}
}
if ideCount > 2 {
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("maximum 2 IDE disks supported (ide2,3 reserved for ISOs)"))
}
if sataCount > 6 {
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("maximum 6 SATA disks supported"))
}
if scsiCount > 31 {
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("maximum 31 SCSI disks supported"))
}
if virtIOCount > 16 {
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("maximum 16 VirtIO disks supported"))
}
if len(c.Serials) > 4 {
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("too many serials: %d serials defined, but proxmox accepts 4 elements maximum", len(c.Serials)))
Expand Down Expand Up @@ -791,6 +848,18 @@ func (c *Config) Prepare(upper interface{}, raws ...interface{}) ([]string, []st
errs = packersdk.MultiErrorAppend(errs, errors.New("efi_storage_pool not set for efi_config"))
}
}
if c.TPMConfig != (tpmConfig{}) {
if c.TPMConfig.TPMStoragePool == "" {
errs = packersdk.MultiErrorAppend(errs, errors.New("tpm_storage_pool not set for tpm_config"))
}
if c.TPMConfig.Version == "" {
log.Printf("TPM state device defined, but no tpm_version given, using v2.0")
c.TPMConfig.Version = "v2.0"
}
if !(c.TPMConfig.Version == "v1.2" || c.TPMConfig.Version == "v2.0") {
errs = packersdk.MultiErrorAppend(errs, errors.New("TPM Version must be one of \"v1.2\", \"v2.0\""))
}
}
if c.Rng0 != (rng0Config{}) {
if !(c.Rng0.Source == "/dev/urandom" || c.Rng0.Source == "/dev/random" || c.Rng0.Source == "/dev/hwrng") {
errs = packersdk.MultiErrorAppend(errs, errors.New("source must be one of \"/dev/urandom\", \"/dev/random\", \"/dev/hwrng\""))
Expand Down
27 changes: 27 additions & 0 deletions builder/proxmox/common/config.hcl2spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 61 additions & 0 deletions builder/proxmox/common/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,67 @@ func TestRng0(t *testing.T) {
}
}

func TestTpm(t *testing.T) {
TpmTest := []struct {
name string
tpm_config tpmConfig
expectFailure bool
}{
{
name: "version 1.2, no error",
expectFailure: false,
tpm_config: tpmConfig{
TPMStoragePool: "local",
Version: "v1.2",
},
},
{
name: "version 2.0, no error",
expectFailure: false,
tpm_config: tpmConfig{
TPMStoragePool: "local",
Version: "v2.0",
},
},
{
name: "empty storage pool, error",
expectFailure: true,
tpm_config: tpmConfig{
TPMStoragePool: "",
Version: "v1.2",
},
},
{
name: "invalid Version, error",
expectFailure: true,
tpm_config: tpmConfig{
TPMStoragePool: "local",
Version: "v6.2",
},
},
}

for _, tt := range TpmTest {
t.Run(tt.name, func(t *testing.T) {
cfg := mandatoryConfig(t)
cfg["tpm_config"] = &tt.tpm_config

var c Config
_, _, err := c.Prepare(&c, cfg)
if err != nil {
if !tt.expectFailure {
t.Fatalf("unexpected failure to prepare config: %s", err)
}
t.Logf("got expected failure: %s", err)
}

if err == nil && tt.expectFailure {
t.Errorf("expected failure, but prepare succeeded")
}
})
}
}

func TestSerials(t *testing.T) {
serialsTest := []struct {
name string
Expand Down
Loading