Skip to content

Commit

Permalink
Adding memory monitor measurement
Browse files Browse the repository at this point in the history
  • Loading branch information
yawangwang committed Dec 21, 2023
1 parent f7d91b3 commit f812084
Show file tree
Hide file tree
Showing 7 changed files with 267 additions and 140 deletions.
1 change: 1 addition & 0 deletions cel/cos_tlv.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const (
OverrideEnvType
// EventContent is empty on success, or contains an error message on failure.
LaunchSeparatorType
MemoryMonitorType
)

// CosTlv is a specific event type created for the COS (Google Container-Optimized OS),
Expand Down
26 changes: 22 additions & 4 deletions launcher/container_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,11 @@ func appendTokenMounts(mounts []specs.Mount) []specs.Mount {
return append(mounts, m)
}

var launchEventSeparator = cel.CosTlv{
EventType: cel.LaunchSeparatorType,
EventContent: nil, // Success
}

// measureContainerClaims will measure various container claims into the COS
// eventlog in the AttestationAgent.
func (r *ContainerRunner) measureContainerClaims(ctx context.Context) error {
Expand Down Expand Up @@ -334,11 +339,20 @@ func (r *ContainerRunner) measureContainerClaims(ctx context.Context) error {
}
}

separator := cel.CosTlv{
EventType: cel.LaunchSeparatorType,
EventContent: nil, // Success
return r.attestAgent.MeasureEvent(launchEventSeparator)
}

// measureHealthMonitoringClaims will measure health monitoring related claims into the COS eventlog in the AttestationAgent.
// For now only memory monitoring will be measured into the COS eventlog, but more measurements (cpu, disk, network, etc.) will be added in the future.
func (r *ContainerRunner) measureHealthMonitoringClaims() error {
var memoryMonitorBit uint8
if r.launchSpec.MemoryMonitoringEnabled {
memoryMonitorBit = 1
}
return r.attestAgent.MeasureEvent(separator)
if err := r.attestAgent.MeasureEvent(cel.CosTlv{EventType: cel.MemoryMonitorType, EventContent: []byte{memoryMonitorBit}}); err != nil {
return err
}
return r.attestAgent.MeasureEvent(launchEventSeparator)
}

// Retrieves the default OIDC token from the attestation service, and returns how long
Expand Down Expand Up @@ -528,6 +542,10 @@ func (r *ContainerRunner) Run(ctx context.Context) error {
} else {
r.logger.Println("MemoryMonitoring is disabled by the VM operator")
}

if err := r.measureHealthMonitoringClaims(); err != nil {
return fmt.Errorf("failed to measure health monitoring claims: %v", err)
}
}

var streamOpt cio.Opt
Expand Down
6 changes: 6 additions & 0 deletions proto/attest.proto
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,16 @@ message SemanticVersion {
uint32 patch = 3;
}

message HealthMonitoringState {
// Whether memory monitoring is enabled.
bool memory_enabled = 1;
}

message AttestedCosState {
ContainerState container = 1;
SemanticVersion cos_version = 2;
SemanticVersion launcher_version = 3;
HealthMonitoringState health_monitoring = 4;
}

message EfiApp {
Expand Down
337 changes: 208 additions & 129 deletions proto/attest/attest.pb.go

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions server/eventlog.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ func contains(set [][]byte, value []byte) bool {
func getVerifiedCosState(coscel cel.CEL) (*pb.AttestedCosState, error) {
cosState := &pb.AttestedCosState{}
cosState.Container = &pb.ContainerState{}
cosState.HealthMonitoring = &pb.HealthMonitoringState{}
cosState.Container.Args = make([]string, 0)
cosState.Container.EnvVars = make(map[string]string)
cosState.Container.OverriddenEnvVars = make(map[string]string)
Expand Down Expand Up @@ -198,6 +199,10 @@ func getVerifiedCosState(coscel cel.CEL) (*pb.AttestedCosState, error) {
cosState.Container.OverriddenEnvVars[envName] = envVal
case cel.LaunchSeparatorType:
seenSeparator = true
case cel.MemoryMonitorType:
if cosTlv.EventContent[0] == uint8(1) {
cosState.HealthMonitoring.MemoryEnabled = true
}
default:
return nil, fmt.Errorf("found unknown COS Event Type %v", cosTlv.EventType)
}
Expand Down
19 changes: 15 additions & 4 deletions server/eventlog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,7 @@ func TestParsingCELEventLog(t *testing.T) {

coscel := &cel.CEL{}
emptyCosState := attestpb.ContainerState{}
emptyHealthMonitoringState := attestpb.HealthMonitoringState{}

var buf bytes.Buffer
// First, encode an empty CEL and try to parse it.
Expand Down Expand Up @@ -672,7 +673,10 @@ func TestParsingCELEventLog(t *testing.T) {
t.Errorf("expecting no error from parseCanonicalEventLog(), but get %v", err)
}
if diff := cmp.Diff(msState.Cos.Container, &emptyCosState, protocmp.Transform()); diff != "" {
t.Errorf("unexpected difference:\n%v", diff)
t.Errorf("unexpected container state difference:\n%v", diff)
}
if diff := cmp.Diff(msState.Cos.HealthMonitoring, &emptyHealthMonitoringState, protocmp.Transform()); diff != "" {
t.Errorf("unexpected health monitoring difference:\n%v", diff)
}
}

Expand All @@ -693,6 +697,7 @@ func TestParsingCELEventLog(t *testing.T) {
{cel.ArgType, cel.CosEventPCR, []byte("--x")},
{cel.ArgType, cel.CosEventPCR, []byte("--y")},
{cel.ArgType, cel.CosEventPCR, []byte("")},
{cel.MemoryMonitorType, cel.CosEventPCR, []byte{1}},
}

expectedEnvVars := make(map[string]string)
Expand All @@ -701,14 +706,17 @@ func TestParsingCELEventLog(t *testing.T) {
expectedEnvVars["baz"] = "foo=bar"
expectedEnvVars["empty"] = ""

want := attestpb.ContainerState{
wantContainerState := attestpb.ContainerState{
ImageReference: string(testCELEvents[0].eventPayload),
ImageDigest: string(testCELEvents[1].eventPayload),
RestartPolicy: attestpb.RestartPolicy_Always,
ImageId: string(testCELEvents[3].eventPayload),
EnvVars: expectedEnvVars,
Args: []string{string(testCELEvents[8].eventPayload), string(testCELEvents[9].eventPayload), string(testCELEvents[10].eventPayload)},
}
wantHealthMonitoringState := attestpb.HealthMonitoringState{
MemoryEnabled: true,
}
for _, testEvent := range testCELEvents {
cos := cel.CosTlv{EventType: testEvent.cosNestedEventType, EventContent: testEvent.eventPayload}
if err := coscel.AppendEvent(tpm, testEvent.pcr, implementedHashes, cos); err != nil {
Expand All @@ -727,8 +735,11 @@ func TestParsingCELEventLog(t *testing.T) {
if msState, err := parseCanonicalEventLog(buf.Bytes(), bank); err != nil {
t.Errorf("expecting no error from parseCanonicalEventLog(), but get %v", err)
} else {
if diff := cmp.Diff(msState.Cos.Container, &want, protocmp.Transform()); diff != "" {
t.Errorf("unexpected difference:\n%v", diff)
if diff := cmp.Diff(msState.Cos.Container, &wantContainerState, protocmp.Transform()); diff != "" {
t.Errorf("unexpected container state difference:\n%v", diff)
}
if diff := cmp.Diff(msState.Cos.HealthMonitoring, &wantHealthMonitoringState, protocmp.Transform()); diff != "" {
t.Errorf("unexpected health monitoring state difference:\n%v", diff)
}
}
}
Expand Down
13 changes: 10 additions & 3 deletions server/verify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,7 @@ func TestVerifyAttestationWithCEL(t *testing.T) {
{cel.ArgType, cel.CosEventPCR, []byte("--y")},
{cel.OverrideArgType, cel.CosEventPCR, []byte("--x")},
{cel.OverrideEnvType, cel.CosEventPCR, []byte("empty=")},
{cel.MemoryMonitorType, cel.CosEventPCR, []byte{1}},
}
for _, testEvent := range testEvents {
cos := cel.CosTlv{EventType: testEvent.cosNestedEventType, EventContent: testEvent.eventPayload}
Expand Down Expand Up @@ -554,7 +555,7 @@ func TestVerifyAttestationWithCEL(t *testing.T) {
expectedOverriddenEnvVars := make(map[string]string)
expectedOverriddenEnvVars["empty"] = ""

want := attestpb.ContainerState{
wantContainerState := attestpb.ContainerState{
ImageReference: string(testEvents[0].eventPayload),
ImageDigest: string(testEvents[1].eventPayload),
RestartPolicy: attestpb.RestartPolicy_Never,
Expand All @@ -564,8 +565,14 @@ func TestVerifyAttestationWithCEL(t *testing.T) {
OverriddenEnvVars: expectedOverriddenEnvVars,
OverriddenArgs: []string{string(testEvents[10].eventPayload)},
}
if diff := cmp.Diff(state.Cos.Container, &want, protocmp.Transform()); diff != "" {
t.Errorf("unexpected difference:\n%v", diff)
wantHealthMonitoringState := attestpb.HealthMonitoringState{
MemoryEnabled: true,
}
if diff := cmp.Diff(state.Cos.Container, &wantContainerState, protocmp.Transform()); diff != "" {
t.Errorf("unexpected container state difference:\n%v", diff)
}
if diff := cmp.Diff(state.Cos.HealthMonitoring, &wantHealthMonitoringState, protocmp.Transform()); diff != "" {
t.Errorf("unexpected health monitoring state difference:\n%v", diff)
}
}

Expand Down

0 comments on commit f812084

Please sign in to comment.