Skip to content

Commit

Permalink
peer-pods: pass policy hash via userdata
Browse files Browse the repository at this point in the history
  • Loading branch information
burgerdev committed Oct 18, 2024
1 parent cfb6771 commit aeacb19
Show file tree
Hide file tree
Showing 6 changed files with 314 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
From 797a113c80c9fd3dfbd4d7b153d3de245c97044f Mon Sep 17 00:00:00 2001
From: Markus Rudy <[email protected]>
Date: Wed, 16 Oct 2024 16:12:19 +0200
Subject: [PATCH] measure agent-config.toml into PCR 10

---
src/cloud-api-adaptor/go.mod | 5 +++-
src/cloud-api-adaptor/go.sum | 2 ++
.../pkg/userdata/provision.go | 27 ++++++++++++++++++-
3 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/src/cloud-api-adaptor/go.mod b/src/cloud-api-adaptor/go.mod
index bd419f6..011870a 100644
--- a/src/cloud-api-adaptor/go.mod
+++ b/src/cloud-api-adaptor/go.mod
@@ -1,6 +1,8 @@
module github.com/confidential-containers/cloud-api-adaptor/src/cloud-api-adaptor

-go 1.21
+go 1.22
+
+toolchain go1.23.2

require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1
@@ -52,6 +54,7 @@ require (
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f
github.com/docker/docker v25.0.5+incompatible
github.com/golang-jwt/jwt/v5 v5.2.1
+ github.com/google/go-tpm v0.9.1
github.com/moby/sys/mountinfo v0.7.1
github.com/pelletier/go-toml/v2 v2.1.0
github.com/sirupsen/logrus v1.9.3
diff --git a/src/cloud-api-adaptor/go.sum b/src/cloud-api-adaptor/go.sum
index 0dd05c2..1ffa1f8 100644
--- a/src/cloud-api-adaptor/go.sum
+++ b/src/cloud-api-adaptor/go.sum
@@ -322,6 +322,8 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-tpm v0.9.1 h1:0pGc4X//bAlmZzMKf8iz6IsDo1nYTbYJ6FZN/rg4zdM=
+github.com/google/go-tpm v0.9.1/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
diff --git a/src/cloud-api-adaptor/pkg/userdata/provision.go b/src/cloud-api-adaptor/pkg/userdata/provision.go
index 5c3b6ca..222d509 100644
--- a/src/cloud-api-adaptor/pkg/userdata/provision.go
+++ b/src/cloud-api-adaptor/pkg/userdata/provision.go
@@ -2,6 +2,7 @@ package userdata

import (
"context"
+ "crypto/sha256"
"fmt"
"log"
"os"
@@ -12,6 +13,8 @@ import (
"github.com/confidential-containers/cloud-api-adaptor/src/cloud-providers/aws"
"github.com/confidential-containers/cloud-api-adaptor/src/cloud-providers/azure"
"github.com/confidential-containers/cloud-api-adaptor/src/cloud-providers/docker"
+ "github.com/google/go-tpm/legacy/tpm2"
+ "github.com/google/go-tpm/tpmutil"
"gopkg.in/yaml.v2"
)

@@ -162,6 +165,7 @@ func findConfigEntry(path string, cc *CloudConfig) []byte {
type entry struct {
path string
optional bool
+ pcrIndex *int
}

func (f *entry) writeFile(cc *CloudConfig) error {
@@ -179,6 +183,10 @@ func (f *entry) writeFile(cc *CloudConfig) error {
return fmt.Errorf("failed to create directory: %w", err)
}

+ if f.pcrIndex != nil {
+ extendPCR(*f.pcrIndex, bytes)
+ }
+
err = os.WriteFile(f.path, bytes, 0644)
if err != nil {
return fmt.Errorf("failed to write file: %w", err)
@@ -189,7 +197,7 @@ func (f *entry) writeFile(cc *CloudConfig) error {

func processCloudConfig(cfg *Config, cc *CloudConfig) error {
entries := []entry{
- {path: cfg.paths.agentConfig, optional: false},
+ {path: cfg.paths.agentConfig, optional: false, pcrIndex: toPtr(10)},
{path: cfg.paths.daemonConfig, optional: false},
{path: cfg.paths.aaConfig, optional: true},
{path: cfg.paths.cdhConfig, optional: true},
@@ -228,3 +236,20 @@ func ProvisionFiles(cfg *Config) error {

return nil
}
+
+func extendPCR(pcrIndex int, data []byte) error {
+ digest := sha256.Sum256(data)
+
+ handle, err := tpm2.OpenTPM()
+ if err != nil {
+ return fmt.Errorf("opening TPM device: %w", err)
+ }
+ if err := tpm2.PCRExtend(handle, tpmutil.Handle(pcrIndex), tpm2.AlgSHA256, digest[:], ""); err != nil {
+ return fmt.Errorf("extending PCR %d: %w", pcrIndex, err)
+ }
+ return nil
+}
+
+func toPtr[A any](a A) *A {
+ return &a
+}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
From 9bb45bab97264a15e36a4b9b9cd06531852d23af Mon Sep 17 00:00:00 2001
From: Markus Rudy <[email protected]>
Date: Thu, 17 Oct 2024 10:20:09 +0200
Subject: [PATCH] set policy digest in agent config

---
src/cloud-api-adaptor/pkg/adaptor/cloud/cloud.go | 2 +-
src/cloud-api-adaptor/pkg/agent/config.go | 10 +++++++++-
src/cloud-api-adaptor/pkg/util/cloud.go | 9 +++++++++
3 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/src/cloud-api-adaptor/pkg/adaptor/cloud/cloud.go b/src/cloud-api-adaptor/pkg/adaptor/cloud/cloud.go
index 5a3ab96..0a83683 100644
--- a/src/cloud-api-adaptor/pkg/adaptor/cloud/cloud.go
+++ b/src/cloud-api-adaptor/pkg/adaptor/cloud/cloud.go
@@ -239,7 +239,7 @@ func (s *cloudService) CreateVM(ctx context.Context, req *pb.CreateVMRequest) (r
logger.Printf("configure agent to use credentials file %s", SrcAuthfilePath)
}

- agentConfig, err := agent.CreateConfigFile(authFilePath)
+ agentConfig, err := agent.CreateConfigFile(authFilePath, util.GetPolicyFromAnnotation(req.Annotations))
if err != nil {
return nil, fmt.Errorf("creating agent config: %w", err)
}
diff --git a/src/cloud-api-adaptor/pkg/agent/config.go b/src/cloud-api-adaptor/pkg/agent/config.go
index 58bcc83..c0d5b58 100644
--- a/src/cloud-api-adaptor/pkg/agent/config.go
+++ b/src/cloud-api-adaptor/pkg/agent/config.go
@@ -1,6 +1,9 @@
package agent

import (
+ "crypto/sha256"
+ "encoding/hex"
+
"github.com/pelletier/go-toml/v2"
)

@@ -13,10 +16,11 @@ const (
type agentConfig struct {
ServerAddr string `toml:"server_addr"`
GuestComponentsProcs string `toml:"guest_components_procs"`
+ PolicySHA256Hex string `toml:"policy_digest_sha256_hex,omitempty"`
ImageRegistryAuth string `toml:"image_registry_auth,omitempty"`
}

-func CreateConfigFile(authJsonPath string) (string, error) {
+func CreateConfigFile(authJsonPath string, policy []byte) (string, error) {
var imageRegistryAuth string
if authJsonPath != "" {
imageRegistryAuth = "file://" + authJsonPath
@@ -27,6 +31,10 @@ func CreateConfigFile(authJsonPath string) (string, error) {
GuestComponentsProcs: GuestComponentsProcs,
ImageRegistryAuth: imageRegistryAuth,
}
+ if policy != nil {
+ digest := sha256.Sum256(policy)
+ config.PolicySHA256Hex = hex.EncodeToString(digest[:])
+ }

bytes, err := toml.Marshal(config)
if err != nil {
diff --git a/src/cloud-api-adaptor/pkg/util/cloud.go b/src/cloud-api-adaptor/pkg/util/cloud.go
index b2ba396..e317495 100644
--- a/src/cloud-api-adaptor/pkg/util/cloud.go
+++ b/src/cloud-api-adaptor/pkg/util/cloud.go
@@ -69,6 +69,15 @@ func GetCPUAndMemoryFromAnnotation(annotations map[string]string) (int64, int64)
return vcpuInt, memoryInt
}

+func GetPolicyFromAnnotation(annotations map[string]string) []byte {
+ // The policy is already base64-decoded in this annotation map.
+ policy, ok := annotations[hypannotations.Policy]
+ if !ok {
+ return nil
+ }
+ return []byte(policy)
+}
+
// Method to check if a string exists in a slice
func Contains(slice []string, s string) bool {
for _, item := range slice {
9 changes: 8 additions & 1 deletion packages/by-name/cloud-api-adaptor/package.nix
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,17 @@ buildGoModule rec {
hash = "sha256-5tDG0sEiRAsb259lPui5ntR6DVHDdcXhb04UESJzHhE=";
};

patches = [
./0001-measure-agent-config.toml-into-PCR-10.patch
./0002-set-policy-digest-in-agent-config.patch
];

patchFlags = ["-p3"];

sourceRoot = "${src.name}/src/cloud-api-adaptor";

proxyVendor = true;
vendorHash = "sha256-kqzi7jRF3tQ4/yLkJXfZly4EvVKFb400/WXlN0WjYm8=";
vendorHash = "sha256-6FWMh2G5yM0QnhpfLS+fRfP6bpPtuGCeCvCNutog3YU=";

nativeBuildInputs = lib.optional withLibvirt pkg-config;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
From e8ad46895101639c1b7af8ff57b4e65d35040cc1 Mon Sep 17 00:00:00 2001
From: Markus Rudy <[email protected]>
Date: Thu, 17 Oct 2024 09:38:35 +0200
Subject: [PATCH] agent: read policy hash from config

---
src/agent/Cargo.lock | 4 ++++
src/agent/Cargo.toml | 1 +
src/agent/src/config.rs | 4 ++++
src/agent/src/policy.rs | 5 ++++-
4 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/src/agent/Cargo.lock b/src/agent/Cargo.lock
index 6c9342ddb..1bfc716d3 100644
--- a/src/agent/Cargo.lock
+++ b/src/agent/Cargo.lock
@@ -2818,6 +2818,7 @@ dependencies = [
"const_format",
"derivative",
"futures",
+ "hex",
"image-rs",
"ipnetwork",
"kata-sys-util",
@@ -6439,6 +6440,9 @@ name = "uuid"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314"
+dependencies = [
+ "serde",
+]

[[package]]
name = "valuable"
diff --git a/src/agent/Cargo.toml b/src/agent/Cargo.toml
index d5b3db965..44612495a 100644
--- a/src/agent/Cargo.toml
+++ b/src/agent/Cargo.toml
@@ -89,6 +89,7 @@ regorus = { version = "0.1.4", default-features = false, features = [
sha2 = { version = "0.10.6", optional = true }
sev = { version = "2.0.2", default-features = false, features = ["snp"], optional = true }
vmm-sys-util = { version = "0.11.0", optional = true }
+hex = "0.4.3"

[dev-dependencies]
tempfile = "3.1.0"
diff --git a/src/agent/src/config.rs b/src/agent/src/config.rs
index a83328440..79fb3037b 100644
--- a/src/agent/src/config.rs
+++ b/src/agent/src/config.rs
@@ -131,6 +131,8 @@ pub struct AgentConfig {
pub image_policy_file: String,
#[cfg(feature = "agent-policy")]
pub policy_file: String,
+ #[cfg(feature = "agent-policy")]
+ pub policy_digest_sha256_hex: String,
}

#[derive(Debug, Deserialize)]
@@ -235,6 +237,8 @@ impl Default for AgentConfig {
image_policy_file: String::from(""),
#[cfg(feature = "agent-policy")]
policy_file: String::from(""),
+ #[cfg(feature = "agent-policy")]
+ policy_digest_sha256_hex: String::from(""),
}
}
}
diff --git a/src/agent/src/policy.rs b/src/agent/src/policy.rs
index 2f1da9ecd..840385fc3 100644
--- a/src/agent/src/policy.rs
+++ b/src/agent/src/policy.rs
@@ -198,7 +198,10 @@ impl AgentPolicy {
}

fn verify_policy_digest(policy: &str) -> Result<()> {
- if let Ok(expected_digest) = get_tdx_mrconfigid() {
+ if !AGENT_CONFIG.policy_digest_sha256_hex.is_empty() {
+ let expected_digest = hex::decode(&AGENT_CONFIG.policy_digest_sha256_hex)?;
+ verify_sha_256(policy, expected_digest.as_slice())
+ } else if let Ok(expected_digest) = get_tdx_mrconfigid() {
info!(sl!(), "policy: TDX MrConfigId ({:?})", expected_digest);

// The MrConfigId used with TDX is longer than the host-data field used
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
From 9128834634ffb1c153eaa243d584b9d21dfcc1a8 Mon Sep 17 00:00:00 2001
From: Markus Rudy <[email protected]>
Date: Fri, 18 Oct 2024 09:58:47 +0200
Subject: [PATCH] runtime: forward policy to remote hypervisor

---
src/runtime/virtcontainers/remote.go | 1 +
1 file changed, 1 insertion(+)

diff --git a/src/runtime/virtcontainers/remote.go b/src/runtime/virtcontainers/remote.go
index 047f09fe8..e95763e44 100644
--- a/src/runtime/virtcontainers/remote.go
+++ b/src/runtime/virtcontainers/remote.go
@@ -81,6 +81,7 @@ func (rh *remoteHypervisor) CreateVM(ctx context.Context, id string, network Net
annotations[hypannotations.DefaultVCPUs] = strconv.FormatUint(uint64(hypervisorConfig.NumVCPUs()), 10)
annotations[hypannotations.DefaultMemory] = strconv.FormatUint(uint64(hypervisorConfig.MemorySize), 10)
annotations[hypannotations.Initdata] = hypervisorConfig.Initdata
+ annotations[hypannotations.Policy] = hypervisorConfig.AgentPolicy

req := &pb.CreateVMRequest{
Id: id,
3 changes: 3 additions & 0 deletions packages/by-name/kata/kata-runtime/package.nix
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ buildGoModule rec {
# The patch is not sufficient for upstream, because it requires the extraRootFs content from
# our Nix packaging.
./0014-tools-don-t-clean-build-root-when-generating-rootfs.patch

./0015-agent-read-policy-hash-from-config.patch
./0016-runtime-forward-policy-to-remote-hypervisor.patch
];
};

Expand Down

0 comments on commit aeacb19

Please sign in to comment.