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

treewide: change runtime-handler naming scheme #772

Merged
merged 2 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all 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: 1 addition & 1 deletion cli/cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func runGenerate(cmd *cobra.Command, args []string) error {
}
}

runtimeHandler, err := mnf.RuntimeHandler(flags.referenceValuesPlatform)
runtimeHandler, err := manifest.RuntimeHandler(flags.referenceValuesPlatform)
if err != nil {
return fmt.Errorf("get runtime handler: %w", err)
}
Expand Down
4 changes: 2 additions & 2 deletions cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"text/tabwriter"

"github.com/edgelesssys/contrast/cli/cmd"
"github.com/edgelesssys/contrast/cli/constants"
"github.com/edgelesssys/contrast/internal/constants"
"github.com/edgelesssys/contrast/internal/manifest"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -43,7 +43,7 @@ func buildVersionString() string {
fmt.Fprintf(versionsWriter, "\t%s\n", image)
}
}
if refValues, err := json.MarshalIndent(manifest.EmbeddedReferenceValues(), "\t", " "); err == nil {
if refValues, err := json.MarshalIndent(manifest.GetEmbeddedReferenceValues(), "\t", " "); err == nil {
fmt.Fprintf(versionsWriter, "embedded reference values:\t%s\n", refValues)
}
fmt.Fprintf(versionsWriter, "genpolicy version:\t%s\n", constants.GenpolicyVersion)
Expand Down
2 changes: 1 addition & 1 deletion cli/telemetry/telemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"net/url"
"runtime"

"github.com/edgelesssys/contrast/cli/constants"
"github.com/edgelesssys/contrast/internal/constants"
"github.com/spf13/cobra"
)

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/examples/emojivoto.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ contrast generate --reference-values aks-clh-snp deployment/
:::note[Runtime class and Initializer]

The deployment YAML shipped for this demo is already configured to be used with Contrast.
A [runtime class](https://docs.edgeless.systems/contrast/components/runtime) `contrast-cc-<VERSIONHASH>`
A [runtime class](https://docs.edgeless.systems/contrast/components/runtime) `contrast-cc-<platform>-<runtime-hash>`
was added to the pods to signal they should be run as Confidential Containers. During the generation process,
the Contrast [Initializer](../components/overview.md#the-initializer) will be added as an init container to these
workloads to facilitate the attestation and certificate pulling before the actual workload is started.
Expand Down
10 changes: 3 additions & 7 deletions docs/docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,7 @@ This should give you output similar to the following one.

```sh
NAME HANDLER AGE
contrast-cc-30bfa8706b542271ec9b7762bbb400af contrast-cc-30bfa8706b542271ec9b7762bbb400af 23d
contrast-cc-4d70a6e266cca46dfa8e41d92874e638 contrast-cc-4d70a6e266cca46dfa8e41d92874e638 7d
contrast-cc-b817659e094106f61bf6c178c27153ba contrast-cc-b817659e094106f61bf6c178c27153ba 2d19h
contrast-cc-beee79ca916b9e5dc59602788cbfb097 contrast-cc-beee79ca916b9e5dc59602788cbfb097 121m
contrast-cc-aks-clh-snp-7173acb5 contrast-cc-aks-clh-snp-7173acb5 23h
kata-cc-isolation kata-cc 45d
```

Expand All @@ -149,8 +146,7 @@ kubectl -n <namespace> get -o=jsonpath='{.spec.runtimeClassName}' pod/<coordinat
The output should list the runtime class the pod is using:

```sh
contrast-cc-beee79ca916b9e5dc59602788cbfb097
contrast-cc-beee79ca916b9e5dc59602788cbfb097
contrast-cc-aks-clh-snp-7173acb5
```

Version information about the currently used CLI can be obtained via the `version` flag:
Expand All @@ -162,7 +158,7 @@ contrast --version
```sh
contrast version v0.X.0
runtime handler: contrast-cc-beee79ca916b9e5dc59602788cbfb097
runtime handler: contrast-cc-aks-clh-snp-7173acb5
launch digest: beee79ca916b9e5dc59602788cbfb097721cde34943e1583a3918f21011a71c47f371f68e883f5e474a6d4053d931a35
genpolicy version: 3.2.0.azl1.genpolicy0
image versions: ghcr.io/edgelesssys/contrast/coordinator@sha256:...
Expand Down
2 changes: 1 addition & 1 deletion e2e/genpolicy/genpolicy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func TestGenpolicy(t *testing.T) {

testCases := kuberesource.GenpolicyRegressionTests()

runtimeHandler, err := manifest.DefaultPlatformHandler(platform)
runtimeHandler, err := manifest.RuntimeHandler(platform)
require.NoError(t, err)

for name, deploy := range testCases {
Expand Down
2 changes: 1 addition & 1 deletion e2e/getdents/getdents_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func TestGetDEnts(t *testing.T) {
// TODO(msanft): Make this configurable
platform := platforms.AKSCloudHypervisorSNP

runtimeHandler, err := manifest.DefaultPlatformHandler(platform)
runtimeHandler, err := manifest.RuntimeHandler(platform)
require.NoError(t, err)

resources := kuberesource.GetDEnts()
Expand Down
2 changes: 1 addition & 1 deletion e2e/openssl/openssl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func TestOpenSSL(t *testing.T) {
// TODO(msanft): Make this configurable
platform := platforms.AKSCloudHypervisorSNP

runtimeHandler, err := manifest.DefaultPlatformHandler(platform)
runtimeHandler, err := manifest.RuntimeHandler(platform)
require.NoError(t, err)

resources := kuberesource.OpenSSL()
Expand Down
2 changes: 1 addition & 1 deletion e2e/policy/policy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func TestPolicy(t *testing.T) {
// TODO(msanft): Make this configurable
platform := platforms.AKSCloudHypervisorSNP

runtimeHandler, err := manifest.DefaultPlatformHandler(platform)
runtimeHandler, err := manifest.RuntimeHandler(platform)
require.NoError(t, err)

resources := kuberesource.OpenSSL()
Expand Down
2 changes: 1 addition & 1 deletion e2e/servicemesh/servicemesh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func TestIngressEgress(t *testing.T) {
// TODO(msanft): Make this configurable
platform := platforms.AKSCloudHypervisorSNP

runtimeHandler, err := manifest.DefaultPlatformHandler(platform)
runtimeHandler, err := manifest.RuntimeHandler(platform)
require.NoError(t, err)

resources := kuberesource.Emojivoto(kuberesource.ServiceMeshIngressEgress)
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions internal/kuberesource/parts.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (

// ContrastRuntimeClass creates a new RuntimeClassConfig.
func ContrastRuntimeClass(platform platforms.Platform) (*RuntimeClassConfig, error) {
runtimeHandler, err := manifest.DefaultPlatformHandler(platform)
runtimeHandler, err := manifest.RuntimeHandler(platform)
if err != nil {
return nil, fmt.Errorf("getting default runtime handler: %w", err)
}
Expand All @@ -45,7 +45,7 @@ type NodeInstallerConfig struct {
func NodeInstaller(namespace string, platform platforms.Platform) (*NodeInstallerConfig, error) {
name := "contrast-node-installer"

runtimeHandler, err := manifest.DefaultPlatformHandler(platform)
runtimeHandler, err := manifest.RuntimeHandler(platform)
if err != nil {
return nil, fmt.Errorf("getting default runtime handler: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/kuberesource/resourcegen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func main() {
log.Fatalf("Error parsing platform: %v", err)
}

runtimeHandler, err = manifest.DefaultPlatformHandler(platform)
runtimeHandler, err = manifest.RuntimeHandler(platform)
if err != nil {
log.Fatalf("Error getting default runtime handler: %v", err)
}
Expand Down
28 changes: 9 additions & 19 deletions internal/manifest/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import (

// Default returns a default manifest with reference values for the given platform.
func Default(platform platforms.Platform) (*Manifest, error) {
refValues := setReferenceValuesIfUninitialized()
embeddedRefValues := GetEmbeddedReferenceValues()
refValues, err := embeddedRefValues.ForPlatform(platform)
if err != nil {
return nil, fmt.Errorf("get reference values for platform %s: %w", platform, err)
}

mnfst := Manifest{}
switch platform {
Expand All @@ -32,29 +36,15 @@ func Default(platform platforms.Platform) (*Manifest, error) {
return &mnfst, nil
}

// DefaultPlatformHandler is a short-hand for getting the default runtime handler for a platform.
func DefaultPlatformHandler(platform platforms.Platform) (string, error) {
mnf, err := Default(platform)
if err != nil {
return "", fmt.Errorf("generating manifest: %w", err)
}
return mnf.RuntimeHandler(platform)
}

// EmbeddedReferenceValues returns the reference values embedded in the binary.
func EmbeddedReferenceValues() ReferenceValues {
return setReferenceValuesIfUninitialized()
}

// EmbeddedReferenceValuesIfUninitialized returns the reference values embedded in the binary.
func setReferenceValuesIfUninitialized() ReferenceValues {
var embeddedReferenceValues *ReferenceValues
// GetEmbeddedReferenceValues returns the reference values embedded in the binary.
func GetEmbeddedReferenceValues() EmbeddedReferenceValues {
var embeddedReferenceValues EmbeddedReferenceValues

if err := json.Unmarshal(EmbeddedReferenceValuesJSON, &embeddedReferenceValues); err != nil {
// As this relies on a constant, predictable value (i.e. the embedded JSON), which -- in a correctly built binary -- should
// unmarshal safely into the [ReferenceValues], it's acceptable to panic here.
panic(fmt.Errorf("failed to unmarshal embedded reference values: %w", err))
}

return *embeddedReferenceValues
return embeddedReferenceValues
}
13 changes: 0 additions & 13 deletions internal/manifest/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"encoding/base64"
"fmt"

"github.com/edgelesssys/contrast/internal/platforms"
"github.com/google/go-sev-guest/abi"
"github.com/google/go-sev-guest/kds"
"github.com/google/go-sev-guest/validate"
Expand Down Expand Up @@ -172,15 +171,3 @@ func (m *Manifest) AKSValidateOpts() (*validate.Options, error) {
PermitProvisionalFirmware: true,
}, nil
}

// RuntimeHandler returns the runtime handler for the given platform.
func (m *Manifest) RuntimeHandler(platform platforms.Platform) (string, error) {
switch platform {
case platforms.AKSCloudHypervisorSNP:
return fmt.Sprintf("contrast-cc-%s", m.ReferenceValues.AKS.TrustedMeasurement[:32]), nil
case platforms.K3sQEMUTDX, platforms.RKE2QEMUTDX:
return fmt.Sprintf("contrast-cc-%s", m.ReferenceValues.BareMetalTDX.TrustedMeasurement[:32]), nil
default:
return "", fmt.Errorf("unsupported platform %s", platform)
}
}
51 changes: 50 additions & 1 deletion internal/manifest/referencevalues.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import (
"encoding/json"
"fmt"
"strconv"
"strings"

"github.com/edgelesssys/contrast/internal/platforms"
)

// EmbeddedReferenceValuesJSON contains the embedded reference values in JSON format.
// At startup, they are unmarshaled into a globally-shared ReferenceValues struct.
//
//go:embed assets/reference-values.json
var EmbeddedReferenceValuesJSON []byte
Expand All @@ -25,6 +27,10 @@ type ReferenceValues struct {
BareMetalTDX *BareMetalTDXReferenceValues `json:"bareMetalTDX,omitempty"`
}

// EmbeddedReferenceValues is a map of runtime handler names to reference values, as
// embedded in the binary.
type EmbeddedReferenceValues map[string]ReferenceValues

// AKSReferenceValues contains reference values for AKS.
type AKSReferenceValues struct {
SNP SNPReferenceValues
Expand Down Expand Up @@ -94,3 +100,46 @@ func (h HexString) String() string {
func (h HexString) Bytes() ([]byte, error) {
return hex.DecodeString(string(h))
}

// ForPlatform returns the reference values for the given platform.
func (e *EmbeddedReferenceValues) ForPlatform(platform platforms.Platform) (*ReferenceValues, error) {
var mapping EmbeddedReferenceValues
if err := json.Unmarshal(EmbeddedReferenceValuesJSON, &mapping); err != nil {
return nil, fmt.Errorf("unmarshal embedded reference values mapping: %w", err)
}

for handler, referenceValues := range mapping {
p, err := platformFromHandler(handler)
if err != nil {
return nil, fmt.Errorf("invalid handler name: %w", err)
}

if p == platform {
return &referenceValues, nil
}
}

return nil, fmt.Errorf("no embedded reference values found for platform: %s", platform)
}

// platformFromHandler extracts the platform from the runtime handler name.
func platformFromHandler(handler string) (platforms.Platform, error) {
rest, found := strings.CutPrefix(handler, "contrast-cc-")
if !found {
return platforms.Unknown, fmt.Errorf("invalid handler name: %s", handler)
}

parts := strings.Split(rest, "-")
if len(parts) != 4 {
return platforms.Unknown, fmt.Errorf("invalid handler name: %s", handler)
}

rawPlatform := fmt.Sprintf("%s-%s-%s", parts[0], parts[1], parts[2])

platform, err := platforms.FromString(rawPlatform)
if err != nil {
return platforms.Unknown, fmt.Errorf("invalid platform in handler name: %w", err)
}

return platform, nil
}
32 changes: 32 additions & 0 deletions internal/manifest/runtimehandler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2024 Edgeless Systems GmbH
// SPDX-License-Identifier: AGPL-3.0-only

package manifest

import (
"encoding/json"
"fmt"

"github.com/edgelesssys/contrast/internal/platforms"
)

// RuntimeHandler returns the name of the runtime handler for the given platform.
func RuntimeHandler(platform platforms.Platform) (string, error) {
var mapping EmbeddedReferenceValues
if err := json.Unmarshal(EmbeddedReferenceValuesJSON, &mapping); err != nil {
return "", fmt.Errorf("unmarshal embedded reference values mapping: %w", err)
}

for runtimeHandler := range mapping {
p, err := platformFromHandler(runtimeHandler)
if err != nil {
return "", fmt.Errorf("invalid runtime handler name %s: %w", runtimeHandler, err)
}

if p == platform {
return runtimeHandler, nil
}
}

return "", fmt.Errorf("no runtime handler found for platform %s", platform)
}
24 changes: 24 additions & 0 deletions internal/manifest/runtimehandler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2024 Edgeless Systems GmbH
// SPDX-License-Identifier: AGPL-3.0-only

package manifest

import (
"testing"

"github.com/edgelesssys/contrast/internal/platforms"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestRuntimeHandler(t *testing.T) {
require := require.New(t)
assert := assert.New(t)
for _, platform := range platforms.All() {
runtimeHandler, err := RuntimeHandler(platform)
require.NoError(err)
assert.NotEmpty(runtimeHandler)
assert.Less(len(runtimeHandler), 64, "runtime handler name can be 63 characters at most")
assert.Regexp(`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`, runtimeHandler, "runtimeHandlerName must be a lowercase RFC 1123 subdomain")
}
}
14 changes: 7 additions & 7 deletions nodeinstaller/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ If desired, you can replace the configuration using a Kubernetes configmap by mo

- `files`: List of files to be installed.
- `files[*].url`: Source of the file's content. Use `http://` or `https://` to download it or `file://` to copy a file from the container image.
- `files[*].path`: Target location of the file on the host filesystem.
- `files[*].path`: Target location of the file on the host filesystem. The `@@runtimeBase@@` placeholder can be used to get a unique per-runtime-handler path.
For example, `@@runtimeBase@@/foo` will resolve to `/opt/edgeless/contrast-cc-<platform>-<runtime-hash>/foo`, where `<platform>` is the platform the node-installer is deployed on,
and `<runtime-hash>` is a hash of all relevant runtime components, so that it's unique per-version.
- `files[*].integrity`: Expected Subresource Integrity (SRI) digest of the file. Only required if URL starts with `http://` or `https://`.
- `runtimeHandlerName`: Name of the container runtime.
- `debugRuntime`: If set to true, enables [serial console access via `vsock`](/dev-docs/aks/serial-console.md). A special, debug-capable IGVM file has to be used for this to work.

Consider the following example:
Expand All @@ -24,25 +25,24 @@ Consider the following example:
"files": [
{
"url": "https://cdn.confidential.cloud/contrast/node-components/2024-03-13/kata-containers.img",
"path": "/opt/edgeless/share/kata-containers.img",
"path": "@@runtimeBase@@/kata-containers.img",
"integrity": "sha256-EdFywKAU+xD0BXmmfbjV4cB6Gqbq9R9AnMWoZFCM3A0="
},
{
"url": "https://cdn.confidential.cloud/contrast/node-components/2024-03-13/kata-containers-igvm.img",
"path": "/opt/edgeless/share/kata-containers-igvm.img",
"path": "@@runtimeBase@@/kata-containers-igvm.img",
"integrity": "sha256-E9Ttx6f9QYwKlQonO/fl1bF2MNBoU4XG3/HHvt9Zv30="
},
{
"url": "https://cdn.confidential.cloud/contrast/node-components/2024-03-13/cloud-hypervisor-cvm",
"path": "/opt/edgeless/bin/cloud-hypervisor-snp",
"path": "@@runtimeBase@@/cloud-hypervisor-snp",
"integrity": "sha256-coTHzd5/QLjlPQfrp9d2TJTIXKNuANTN7aNmpa8PRXo="
},
{
"url": "file:///opt/edgeless/bin/containerd-shim-contrast-cc-v2",
"path": "/opt/edgeless/bin/containerd-shim-contrast-cc-v2",
"path": "@@runtimeBase@@/containerd-shim-contrast-cc-v2",
}
],
"runtimeHandlerName": "contrast-cc",
"debugRuntime": false
}
```
Loading