Skip to content

Commit c596cca

Browse files
committed
runtime/nodeinstaller: add insecure platform variants
1 parent 58434e3 commit c596cca

16 files changed

Lines changed: 672 additions & 31 deletions

File tree

internal/atls/issuer/issuer_linux.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
package issuer
77

88
import (
9-
"fmt"
109
"log/slog"
1110

1211
"github.com/edgelesssys/contrast/internal/atls"
12+
"github.com/edgelesssys/contrast/internal/attestation/insecure"
1313
snpissuer "github.com/edgelesssys/contrast/internal/attestation/snp/issuer"
1414
tdxissuer "github.com/edgelesssys/contrast/internal/attestation/tdx/issuer"
1515
"github.com/edgelesssys/contrast/internal/logger"
@@ -29,6 +29,7 @@ func New(log *slog.Logger) (atls.Issuer, error) {
2929
logger.NewWithAttrs(logger.NewNamed(log, "issuer"), map[string]string{"tee-type": "tdx"}),
3030
), nil
3131
default:
32-
return nil, fmt.Errorf("unsupported platform: %T", cpuid.CPU)
32+
log.Warn("No TEE platform detected, using insecure attestation issuer")
33+
return insecure.NewIssuer(), nil
3334
}
3435
}

internal/kuberesource/parts.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@ func ContrastRuntimeClass(platform platforms.Platform) (*RuntimeClassConfig, err
2828

2929
// Consists of the default VM memory, 70MiB for the Kata shim and 100MiB for qemu overhead.
3030
memoryOverhead := platforms.DefaultMemoryInMebiBytes(platform) + 170
31+
if platforms.IsInsecure(platform) && platforms.IsGPU(platform) {
32+
// On insecure (non-CC) GPU platforms, iommufd VFIO passthrough pins guest
33+
// memory and allocates IOMMU page tables that are charged to the pod's
34+
// cgroup. On CC platforms, TDX manages this memory outside the cgroup.
35+
// (in the kernel / TDX module memory)
36+
// Add extra headroom to avoid OOM kills. 512MB should suffice for VMs up
37+
// to ~256GB of memory, which is our current limit on TDX as well.
38+
memoryOverhead += 512
39+
}
3140

3241
r := RuntimeClass(runtimeHandler).
3342
WithHandler(runtimeHandler).

internal/manifest/runtimehandler.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ func RuntimeHandler(platform platforms.Platform) (string, error) {
3333
// PlatformFromHandler extracts the platform from the runtime handler name.
3434
func PlatformFromHandler(handler string) (platforms.Platform, error) {
3535
rest, found := strings.CutPrefix(handler, "contrast-cc-")
36+
isInsecure := false
37+
if !found {
38+
rest, found = strings.CutPrefix(handler, "contrast-insecure-")
39+
isInsecure = true
40+
}
3641
if !found {
3742
return platforms.Unknown, fmt.Errorf("invalid handler name: %s", handler)
3843
}
@@ -43,6 +48,9 @@ func PlatformFromHandler(handler string) (platforms.Platform, error) {
4348
}
4449

4550
rawPlatform := strings.Join(parts[:len(parts)-1], "-")
51+
if isInsecure {
52+
rawPlatform += "-insecure"
53+
}
4654

4755
platform, err := platforms.FromString(rawPlatform)
4856
if err != nil {

internal/platforms/platforms.go

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,22 @@ const (
2424
MetalQEMUSNPGPU
2525
// MetalQEMUTDXGPU is the generic platform for bare-metal TDX deployments with GPU passthrough.
2626
MetalQEMUTDXGPU
27+
// MetalQEMUSNPInsecure is the platform for bare-metal SNP deployments with a non-CC runtime class.
28+
MetalQEMUSNPInsecure
29+
// MetalQEMUTDXInsecure is the platform for bare-metal TDX deployments with a non-CC runtime class.
30+
MetalQEMUTDXInsecure
31+
// MetalQEMUSNPGPUInsecure is the platform for bare-metal SNP deployments with GPU passthrough and a non-CC runtime class.
32+
MetalQEMUSNPGPUInsecure
33+
// MetalQEMUTDXGPUInsecure is the platform for bare-metal TDX deployments with GPU passthrough and a non-CC runtime class.
34+
MetalQEMUTDXGPUInsecure
2735
)
2836

2937
// All returns a list of all available platforms.
3038
func All() []Platform {
31-
return []Platform{MetalQEMUSNP, MetalQEMUTDX, MetalQEMUSNPGPU, MetalQEMUTDXGPU}
39+
return []Platform{
40+
MetalQEMUSNP, MetalQEMUTDX, MetalQEMUSNPGPU, MetalQEMUTDXGPU,
41+
MetalQEMUSNPInsecure, MetalQEMUTDXInsecure, MetalQEMUSNPGPUInsecure, MetalQEMUTDXGPUInsecure,
42+
}
3243
}
3344

3445
// AllStrings returns a list of all available platforms as strings.
@@ -51,11 +62,36 @@ func (p Platform) String() string {
5162
return "Metal-QEMU-TDX"
5263
case MetalQEMUTDXGPU:
5364
return "Metal-QEMU-TDX-GPU"
65+
case MetalQEMUSNPInsecure:
66+
return "Metal-QEMU-SNP-Insecure"
67+
case MetalQEMUTDXInsecure:
68+
return "Metal-QEMU-TDX-Insecure"
69+
case MetalQEMUSNPGPUInsecure:
70+
return "Metal-QEMU-SNP-GPU-Insecure"
71+
case MetalQEMUTDXGPUInsecure:
72+
return "Metal-QEMU-TDX-GPU-Insecure"
5473
default:
5574
return "Unknown"
5675
}
5776
}
5877

78+
// InsecureVariant returns the insecure (non-CC) variant of the
79+
// platform, or Unknown if there is no such variant.
80+
func (p Platform) InsecureVariant() Platform {
81+
switch p {
82+
case MetalQEMUSNP:
83+
return MetalQEMUSNPInsecure
84+
case MetalQEMUTDX:
85+
return MetalQEMUTDXInsecure
86+
case MetalQEMUSNPGPU:
87+
return MetalQEMUSNPGPUInsecure
88+
case MetalQEMUTDXGPU:
89+
return MetalQEMUTDXGPUInsecure
90+
default:
91+
return Unknown
92+
}
93+
}
94+
5995
// MarshalJSON marshals a Platform type to a JSON string.
6096
func (p Platform) MarshalJSON() ([]byte, error) {
6197
return fmt.Appendf(nil, `"%s"`, p.String()), nil
@@ -99,6 +135,14 @@ func FromString(s string) (Platform, error) {
99135
return MetalQEMUTDX, nil
100136
case "metal-qemu-tdx-gpu":
101137
return MetalQEMUTDXGPU, nil
138+
case "metal-qemu-snp-insecure":
139+
return MetalQEMUSNPInsecure, nil
140+
case "metal-qemu-tdx-insecure":
141+
return MetalQEMUTDXInsecure, nil
142+
case "metal-qemu-snp-gpu-insecure":
143+
return MetalQEMUSNPGPUInsecure, nil
144+
case "metal-qemu-tdx-gpu-insecure":
145+
return MetalQEMUTDXGPUInsecure, nil
102146
default:
103147
return Unknown, fmt.Errorf("unknown platform: %s", s)
104148
}
@@ -121,10 +165,18 @@ func FromRuntimeClassString(s string) (Platform, error) {
121165
return MetalQEMUSNPGPU, nil
122166
case strings.HasPrefix(s, "contrast-cc-metal-qemu-snp"):
123167
return MetalQEMUSNP, nil
168+
case strings.HasPrefix(s, "contrast-insecure-metal-qemu-snp-gpu"):
169+
return MetalQEMUSNPGPUInsecure, nil
170+
case strings.HasPrefix(s, "contrast-insecure-metal-qemu-snp"):
171+
return MetalQEMUSNPInsecure, nil
124172
case strings.HasPrefix(s, "contrast-cc-metal-qemu-tdx-gpu"):
125173
return MetalQEMUTDXGPU, nil
126174
case strings.HasPrefix(s, "contrast-cc-metal-qemu-tdx"):
127175
return MetalQEMUTDX, nil
176+
case strings.HasPrefix(s, "contrast-insecure-metal-qemu-tdx-gpu"):
177+
return MetalQEMUTDXGPUInsecure, nil
178+
case strings.HasPrefix(s, "contrast-insecure-metal-qemu-tdx"):
179+
return MetalQEMUTDXInsecure, nil
128180
default:
129181
return Unknown, fmt.Errorf("unknown platform: %s", s)
130182
}
@@ -133,7 +185,7 @@ func FromRuntimeClassString(s string) (Platform, error) {
133185
// DefaultMemoryInMebiBytes returns the desired VM overhead for the given platform.
134186
func DefaultMemoryInMebiBytes(p Platform) int {
135187
switch p {
136-
case MetalQEMUSNPGPU, MetalQEMUTDXGPU:
188+
case MetalQEMUSNPGPU, MetalQEMUTDXGPU, MetalQEMUSNPGPUInsecure, MetalQEMUTDXGPUInsecure:
137189
// Guest components contribute around 600MiB with GPU enabled.
138190
return 1024
139191
default:
@@ -144,6 +196,16 @@ func DefaultMemoryInMebiBytes(p Platform) int {
144196
}
145197
}
146198

199+
// IsInsecure returns true if the platform is an insecure (non-CC) platform.
200+
func IsInsecure(p Platform) bool {
201+
switch p {
202+
case MetalQEMUSNPInsecure, MetalQEMUTDXInsecure, MetalQEMUSNPGPUInsecure, MetalQEMUTDXGPUInsecure:
203+
return true
204+
default:
205+
return false
206+
}
207+
}
208+
147209
// IsSNP returns true if the platform is a SEV-SNP platform.
148210
func IsSNP(p Platform) bool {
149211
switch p {
@@ -167,7 +229,7 @@ func IsTDX(p Platform) bool {
167229
// IsGPU returns true if the platform supports GPUs.
168230
func IsGPU(p Platform) bool {
169231
switch p {
170-
case MetalQEMUSNPGPU, MetalQEMUTDXGPU:
232+
case MetalQEMUSNPGPU, MetalQEMUTDXGPU, MetalQEMUSNPGPUInsecure, MetalQEMUTDXGPUInsecure:
171233
return true
172234
default:
173235
return false
@@ -177,7 +239,8 @@ func IsGPU(p Platform) bool {
177239
// IsQEMU returns true if the platform uses QEMU as the hypervisor.
178240
func IsQEMU(p Platform) bool {
179241
switch p {
180-
case MetalQEMUSNP, MetalQEMUSNPGPU, MetalQEMUTDX, MetalQEMUTDXGPU:
242+
case MetalQEMUSNP, MetalQEMUSNPGPU, MetalQEMUTDX, MetalQEMUTDXGPU,
243+
MetalQEMUSNPInsecure, MetalQEMUTDXInsecure, MetalQEMUSNPGPUInsecure, MetalQEMUTDXGPUInsecure:
181244
return true
182245
default:
183246
return false
@@ -191,6 +254,10 @@ func (p Platform) WithGPU() Platform {
191254
return MetalQEMUSNPGPU
192255
case MetalQEMUTDX, MetalQEMUTDXGPU:
193256
return MetalQEMUTDXGPU
257+
case MetalQEMUSNPInsecure, MetalQEMUSNPGPUInsecure:
258+
return MetalQEMUSNPGPUInsecure
259+
case MetalQEMUTDXInsecure, MetalQEMUTDXGPUInsecure:
260+
return MetalQEMUTDXGPUInsecure
194261
default:
195262
return Unknown
196263
}

justfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ node-installer platform=default_platform:
5858
#!/usr/bin/env bash
5959
set -euo pipefail
6060
case {{ platform }} in
61-
"Metal-QEMU-SNP"|"Metal-QEMU-TDX")
61+
"Metal-QEMU-SNP"|"Metal-QEMU-TDX"|"Metal-QEMU-SNP-Insecure"|"Metal-QEMU-TDX-Insecure")
6262
just push "node-installer-kata"
6363
;;
64-
"Metal-QEMU-SNP-GPU"|"Metal-QEMU-TDX-GPU")
64+
"Metal-QEMU-SNP-GPU"|"Metal-QEMU-TDX-GPU"|"Metal-QEMU-SNP-GPU-Insecure"|"Metal-QEMU-TDX-GPU-Insecure")
6565
just push "node-installer-kata-gpu"
6666
;;
6767
*)
@@ -169,7 +169,7 @@ runtime target=default_deploy_target platform=default_platform set=default_set:
169169
--namespace {{ target }}${namespace_suffix-} \
170170
--node-installer-target-conf-type ${node_installer_target_conf_type} \
171171
--platform "$platforms" \
172-
runtime >> "./{{ workspace_dir }}/runtime/runtime.yml"
172+
runtime > "./{{ workspace_dir }}/runtime/runtime.yml"
173173

174174
# Populate the workspace with a Kubernetes deployment
175175
populate target=default_deploy_target platform=default_platform set=default_set:

nodeinstaller/internal/containerdconfig/config.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,12 @@ func ContrastRuntime(baseDir string, platform platforms.Platform) (Runtime, erro
144144
PrivilegedWithoutHostDevices: true,
145145
}
146146

147-
switch {
148-
case platforms.IsTDX(platform):
147+
switch platform {
148+
case platforms.MetalQEMUTDX, platforms.MetalQEMUTDXGPU, platforms.MetalQEMUTDXInsecure, platforms.MetalQEMUTDXGPUInsecure:
149149
cfg.Options = map[string]any{
150150
"ConfigPath": filepath.Join(baseDir, "etc", "configuration-qemu-tdx.toml"),
151151
}
152-
case platforms.IsSNP(platform):
152+
case platforms.MetalQEMUSNP, platforms.MetalQEMUSNPGPU, platforms.MetalQEMUSNPInsecure, platforms.MetalQEMUSNPGPUInsecure:
153153
cfg.Options = map[string]any{
154154
"ConfigPath": filepath.Join(baseDir, "etc", "configuration-qemu-snp.toml"),
155155
}

nodeinstaller/internal/kataconfig/config.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,30 +39,39 @@ func KataRuntimeConfig(
3939
) (*Config, error) {
4040
var customContrastAnnotations []string
4141
var config Config
42-
switch {
43-
case platforms.IsTDX(platform):
42+
switch platform {
43+
case platforms.MetalQEMUTDX, platforms.MetalQEMUTDXGPU, platforms.MetalQEMUTDXInsecure, platforms.MetalQEMUTDXGPUInsecure:
4444
if err := toml.Unmarshal([]byte(kataBareMetalQEMUTDXBaseConfig), &config); err != nil {
4545
return nil, fmt.Errorf("failed to unmarshal kata runtime configuration: %w", err)
4646
}
4747
config.Hypervisor["qemu"]["firmware"] = filepath.Join(baseDir, "tdx", "share", "OVMF.fd")
4848
// We set up dm_verity in the system NixOS config.
4949
// Doing so again here prevents VM boots.
5050
config.Hypervisor["qemu"]["kernel_verity_params"] = ""
51-
case platforms.IsSNP(platform):
51+
case platforms.MetalQEMUSNP, platforms.MetalQEMUSNPGPU, platforms.MetalQEMUSNPInsecure, platforms.MetalQEMUSNPGPUInsecure:
5252
if err := toml.Unmarshal([]byte(kataBareMetalQEMUSNPBaseConfig), &config); err != nil {
5353
return nil, fmt.Errorf("failed to unmarshal kata runtime configuration: %w", err)
5454
}
5555

56-
for _, productLine := range []string{"_Milan", "_Genoa"} {
57-
for _, annotationType := range []string{"snp_id_block", "snp_id_auth", "snp_guest_policy"} {
58-
customContrastAnnotations = append(customContrastAnnotations, annotationType+productLine)
56+
if !platforms.IsInsecure(platform) {
57+
for _, productLine := range []string{"_Milan", "_Genoa"} {
58+
for _, annotationType := range []string{"snp_id_block", "snp_id_auth", "snp_guest_policy"} {
59+
customContrastAnnotations = append(customContrastAnnotations, annotationType+productLine)
60+
}
5961
}
6062
}
6163

6264
config.Hypervisor["qemu"]["firmware"] = filepath.Join(baseDir, "snp", "share", "OVMF.fd")
6365
default:
6466
return nil, fmt.Errorf("unsupported platform: %s", platform)
6567
}
68+
// Disable confidential computing features for insecure platforms.
69+
if platforms.IsInsecure(platform) {
70+
config.Hypervisor["qemu"]["confidential_guest"] = false
71+
if platforms.IsSNP(platform) || platform == platforms.MetalQEMUSNPInsecure || platform == platforms.MetalQEMUSNPGPUInsecure {
72+
config.Hypervisor["qemu"]["sev_snp_guest"] = false
73+
}
74+
}
6675
if debug {
6776
config.Agent["kata"]["enable_debug"] = true
6877
config.Agent["kata"]["debug_console_enabled"] = true

nodeinstaller/internal/kataconfig/config_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ var (
2222
expectedConfMetalQEMUSNPGPU []byte
2323
//go:embed testdata/expected-configuration-qemu-tdx-gpu.toml
2424
expectedConfMetalQEMUTDXGPU []byte
25+
//go:embed testdata/expected-configuration-qemu-snp-insecure.toml
26+
expectedConfMetalQEMUSNPInsecure []byte
27+
//go:embed testdata/expected-configuration-qemu-tdx-insecure.toml
28+
expectedConfMetalQEMUTDXInsecure []byte
29+
//go:embed testdata/expected-configuration-qemu-snp-gpu-insecure.toml
30+
expectedConfMetalQEMUSNPGPUInsecure []byte
31+
//go:embed testdata/expected-configuration-qemu-tdx-gpu-insecure.toml
32+
expectedConfMetalQEMUTDXGPUInsecure []byte
2533
)
2634

2735
func TestKataRuntimeConfig(t *testing.T) {
@@ -45,6 +53,22 @@ func TestKataRuntimeConfig(t *testing.T) {
4553
changeSnpFields: false,
4654
want: string(expectedConfMetalQEMUTDXGPU),
4755
},
56+
platforms.MetalQEMUSNPInsecure: {
57+
changeSnpFields: true,
58+
want: string(expectedConfMetalQEMUSNPInsecure),
59+
},
60+
platforms.MetalQEMUTDXInsecure: {
61+
changeSnpFields: false,
62+
want: string(expectedConfMetalQEMUTDXInsecure),
63+
},
64+
platforms.MetalQEMUSNPGPUInsecure: {
65+
changeSnpFields: true,
66+
want: string(expectedConfMetalQEMUSNPGPUInsecure),
67+
},
68+
platforms.MetalQEMUTDXGPUInsecure: {
69+
changeSnpFields: false,
70+
want: string(expectedConfMetalQEMUTDXGPUInsecure),
71+
},
4872
}
4973
for platform, tc := range testCases {
5074
t.Run(platform.String(), func(t *testing.T) {

0 commit comments

Comments
 (0)