mirror of
https://github.com/ultravioletrs/cocos.git
synced 2026-06-23 04:10:25 +00:00
NOISSUE - Add path to expected PCR values (#398)
* add path to expected PCR values * change rust scrtip for attestation policy to print policy to stdout * fix cli test * remove stdout from cmd config struct * fix manager test * fix manager readme
This commit is contained in:
committed by
GitHub
parent
33744a12a8
commit
293c65a3aa
+14
-29
@@ -1,48 +1,46 @@
|
||||
// Copyright (c) Ultraviolet
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
package igvmmeasure
|
||||
package cmdconfig
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var IgvmMeasureOptions = []string{"measure", "-b"}
|
||||
|
||||
type MeasurementProvider interface {
|
||||
Run(igvmBinaryPath string) error
|
||||
Run(binaryPath string) ([]byte, error)
|
||||
Stop() error
|
||||
}
|
||||
type IgvmMeasurement struct {
|
||||
type CmdConfig struct {
|
||||
binPath string
|
||||
options []string
|
||||
stderr io.Writer
|
||||
stdout io.Writer
|
||||
cmd *exec.Cmd
|
||||
execCommand func(name string, arg ...string) *exec.Cmd
|
||||
}
|
||||
|
||||
func NewIgvmMeasurement(binPath string, stderr, stdout io.Writer) (*IgvmMeasurement, error) {
|
||||
func NewCmdConfig(binPath string, options []string, stderr io.Writer) (*CmdConfig, error) {
|
||||
if binPath == "" {
|
||||
return nil, fmt.Errorf("pathToBinary cannot be empty")
|
||||
}
|
||||
|
||||
return &IgvmMeasurement{
|
||||
return &CmdConfig{
|
||||
binPath: binPath,
|
||||
options: options,
|
||||
stderr: stderr,
|
||||
stdout: stdout,
|
||||
execCommand: exec.Command,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *IgvmMeasurement) Run(pathToFile string) error {
|
||||
func (m *CmdConfig) Run(pathToFile string) ([]byte, error) {
|
||||
binary := m.binPath
|
||||
args := []string{}
|
||||
args = append(args, m.options...)
|
||||
args = append(args, pathToFile)
|
||||
args = append(args, "measure")
|
||||
args = append(args, "-b")
|
||||
args = append(args, m.options...)
|
||||
|
||||
outBuf := &bytes.Buffer{}
|
||||
cmd := m.execCommand(binary, args...)
|
||||
@@ -50,26 +48,13 @@ func (m *IgvmMeasurement) Run(pathToFile string) error {
|
||||
cmd.Stdout = outBuf
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
outputString := outBuf.String()
|
||||
|
||||
lines := strings.Split(strings.TrimSpace(outputString), "\n")
|
||||
|
||||
if len(lines) == 1 {
|
||||
outputString = strings.ToLower(outputString)
|
||||
_, err := m.stdout.Write([]byte(outputString))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("error: %s", outputString)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil
|
||||
return outBuf.Bytes(), nil
|
||||
}
|
||||
|
||||
func (m *IgvmMeasurement) Stop() error {
|
||||
func (m *CmdConfig) Stop() error {
|
||||
if m.cmd == nil || m.cmd.Process == nil {
|
||||
return fmt.Errorf("no running process to stop")
|
||||
}
|
||||
@@ -82,6 +67,6 @@ func (m *IgvmMeasurement) Stop() error {
|
||||
}
|
||||
|
||||
// SetExecCommand allows tests to inject a mock execCommand function.
|
||||
func (m *IgvmMeasurement) SetExecCommand(cmdFunc func(name string, arg ...string) *exec.Cmd) {
|
||||
func (m *CmdConfig) SetExecCommand(cmdFunc func(name string, arg ...string) *exec.Cmd) {
|
||||
m.execCommand = cmdFunc
|
||||
}
|
||||
+9
-10
@@ -1,6 +1,6 @@
|
||||
// Copyright (c) Ultraviolet
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
package igvmmeasure
|
||||
package cmdconfig
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -14,15 +14,15 @@ import (
|
||||
func TestIgvmMeasurement(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
setup func() *IgvmMeasurement
|
||||
setup func() *CmdConfig
|
||||
runArgs string
|
||||
expectErr bool
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
name: "NewIgvmMeasurement - Empty pathToBinary",
|
||||
setup: func() *IgvmMeasurement {
|
||||
igvm, err := NewIgvmMeasurement("", nil, nil)
|
||||
setup: func() *CmdConfig {
|
||||
igvm, err := NewCmdConfig("", []string{""}, nil)
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, igvm)
|
||||
return nil
|
||||
@@ -32,8 +32,8 @@ func TestIgvmMeasurement(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Run - Successful Execution",
|
||||
setup: func() *IgvmMeasurement {
|
||||
igvm, _ := NewIgvmMeasurement("/valid/path", nil, nil)
|
||||
setup: func() *CmdConfig {
|
||||
igvm, _ := NewCmdConfig("/valid/path", []string{""}, nil)
|
||||
igvm.SetExecCommand(func(name string, arg ...string) *exec.Cmd {
|
||||
return exec.Command("sh", "-c", "echo 'measurement successful'")
|
||||
})
|
||||
@@ -43,8 +43,8 @@ func TestIgvmMeasurement(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Run - Failure Execution",
|
||||
setup: func() *IgvmMeasurement {
|
||||
igvm, _ := NewIgvmMeasurement("/invalid/path", nil, nil)
|
||||
setup: func() *CmdConfig {
|
||||
igvm, _ := NewCmdConfig("/invalid/path", []string{""}, nil)
|
||||
igvm.SetExecCommand(func(name string, arg ...string) *exec.Cmd {
|
||||
return exec.Command("sh", "-c", "echo 'some error occurred\nextra line' && exit 1")
|
||||
})
|
||||
@@ -61,10 +61,9 @@ func TestIgvmMeasurement(t *testing.T) {
|
||||
|
||||
if igvm != nil {
|
||||
buf := new(bytes.Buffer)
|
||||
igvm.stdout = buf
|
||||
igvm.stderr = buf
|
||||
|
||||
err := igvm.Run(tc.runArgs)
|
||||
_, err := igvm.Run(tc.runArgs)
|
||||
if tc.expectErr {
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, strings.TrimSpace(tc.expectedErr), strings.TrimSpace(err.Error()))
|
||||
@@ -21,10 +21,11 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
AttestationPolicy = Config{SnpCheck: &check.Config{Policy: &check.Policy{}, RootOfTrust: &check.RootOfTrust{}}, PcrConfig: &PcrConfig{}}
|
||||
AttestationPolicy = Config{Config: &check.Config{Policy: &check.Policy{}, RootOfTrust: &check.RootOfTrust{}}, PcrConfig: &PcrConfig{}}
|
||||
ErrAttestationPolicyOpen = errors.New("failed to open Attestation Policy file")
|
||||
ErrAttestationPolicyDecode = errors.New("failed to decode Attestation Policy file")
|
||||
ErrAttestationPolicyMissing = errors.New("failed due to missing Attestation Policy file")
|
||||
ErrAttestationPolicyEncode = errors.New("failed to encode the Attestation Policy")
|
||||
)
|
||||
|
||||
type PcrValues struct {
|
||||
@@ -37,8 +38,8 @@ type PcrConfig struct {
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
SnpCheck *check.Config
|
||||
PcrConfig *PcrConfig
|
||||
*check.Config
|
||||
*PcrConfig
|
||||
}
|
||||
|
||||
func ReadAttestationPolicy(policyPath string, attestationConfiguration *Config) error {
|
||||
@@ -57,7 +58,7 @@ func ReadAttestationPolicy(policyPath string, attestationConfiguration *Config)
|
||||
func ReadAttestationPolicyFromByte(policyData []byte, attestationConfiguration *Config) error {
|
||||
unmarshalOptions := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true}
|
||||
|
||||
if err := unmarshalOptions.Unmarshal(policyData, attestationConfiguration.SnpCheck); err != nil {
|
||||
if err := unmarshalOptions.Unmarshal(policyData, attestationConfiguration.Config); err != nil {
|
||||
return errors.Wrap(ErrAttestationPolicyDecode, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ func GetLeveledQuoteProvider() (client.LeveledQuoteProvider, error) {
|
||||
}
|
||||
|
||||
func VerifyAttestationReportTLS(attestationPB *sevsnp.Attestation, reportData []byte) error {
|
||||
config, err := copyConfig(config.AttestationPolicy.SnpCheck)
|
||||
config, err := copyConfig(config.AttestationPolicy.Config)
|
||||
if err != nil {
|
||||
return errors.Wrap(fmt.Errorf("failed to create a copy of attestation policy"), err)
|
||||
}
|
||||
|
||||
@@ -145,8 +145,8 @@ func TestVerifyAttestationReportUnknownProduct(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
config.AttestationPolicy.SnpCheck.RootOfTrust.ProductLine = ""
|
||||
config.AttestationPolicy.SnpCheck.Policy.Product = nil
|
||||
config.AttestationPolicy.Config.RootOfTrust.ProductLine = ""
|
||||
config.AttestationPolicy.Config.Policy.Product = nil
|
||||
err := VerifyAttestationReportTLS(tt.attestationReport, tt.reportData)
|
||||
assert.True(t, errors.Contains(err, tt.err), fmt.Sprintf("expected error %v, got %v", tt.err, err))
|
||||
})
|
||||
@@ -192,23 +192,23 @@ func prepVerifyAttReport(t *testing.T) (*sevsnp.Attestation, []byte) {
|
||||
rr, err := abi.ReportCertsToProto(file)
|
||||
require.NoError(t, err)
|
||||
|
||||
config.AttestationPolicy = config.Config{SnpCheck: &check.Config{Policy: &check.Policy{}, RootOfTrust: &check.RootOfTrust{}}, PcrConfig: &config.PcrConfig{}}
|
||||
config.AttestationPolicy = config.Config{Config: &check.Config{Policy: &check.Policy{}, RootOfTrust: &check.RootOfTrust{}}, PcrConfig: &config.PcrConfig{}}
|
||||
|
||||
attestationPolicyFile, err := os.ReadFile("../../../scripts/attestation_policy/attestation_policy.json")
|
||||
require.NoError(t, err)
|
||||
|
||||
unmarshalOptions := protojson.UnmarshalOptions{DiscardUnknown: true}
|
||||
|
||||
err = unmarshalOptions.Unmarshal(attestationPolicyFile, config.AttestationPolicy.SnpCheck)
|
||||
err = unmarshalOptions.Unmarshal(attestationPolicyFile, config.AttestationPolicy.Config)
|
||||
require.NoError(t, err)
|
||||
|
||||
config.AttestationPolicy.SnpCheck.Policy.Product = &sevsnp.SevProduct{Name: sevsnp.SevProduct_SEV_PRODUCT_MILAN}
|
||||
config.AttestationPolicy.SnpCheck.Policy.FamilyId = rr.Report.FamilyId
|
||||
config.AttestationPolicy.SnpCheck.Policy.ImageId = rr.Report.ImageId
|
||||
config.AttestationPolicy.SnpCheck.Policy.Measurement = rr.Report.Measurement
|
||||
config.AttestationPolicy.SnpCheck.Policy.HostData = rr.Report.HostData
|
||||
config.AttestationPolicy.SnpCheck.Policy.ReportIdMa = rr.Report.ReportIdMa
|
||||
config.AttestationPolicy.SnpCheck.RootOfTrust.ProductLine = sevProductNameMilan
|
||||
config.AttestationPolicy.Config.Policy.Product = &sevsnp.SevProduct{Name: sevsnp.SevProduct_SEV_PRODUCT_MILAN}
|
||||
config.AttestationPolicy.Config.Policy.FamilyId = rr.Report.FamilyId
|
||||
config.AttestationPolicy.Config.Policy.ImageId = rr.Report.ImageId
|
||||
config.AttestationPolicy.Config.Policy.Measurement = rr.Report.Measurement
|
||||
config.AttestationPolicy.Config.Policy.HostData = rr.Report.HostData
|
||||
config.AttestationPolicy.Config.Policy.ReportIdMa = rr.Report.ReportIdMa
|
||||
config.AttestationPolicy.Config.RootOfTrust.ProductLine = sevProductNameMilan
|
||||
|
||||
return rr, rr.Report.ReportData
|
||||
}
|
||||
|
||||
@@ -251,13 +251,13 @@ func TestReadAttestationPolicy(t *testing.T) {
|
||||
defer os.Remove(tt.manifestPath)
|
||||
}
|
||||
|
||||
config := att.Config{SnpCheck: &check.Config{}, PcrConfig: &att.PcrConfig{}}
|
||||
config := att.Config{Config: &check.Config{}, PcrConfig: &att.PcrConfig{}}
|
||||
err := att.ReadAttestationPolicy(tt.manifestPath, &config)
|
||||
|
||||
assert.True(t, errors.Contains(err, tt.err), fmt.Sprintf("expected error %v, got %v", tt.err, err))
|
||||
if tt.err == nil {
|
||||
assert.NotNil(t, config.SnpCheck.Policy)
|
||||
assert.NotNil(t, config.SnpCheck.RootOfTrust)
|
||||
assert.NotNil(t, config.Config.Policy)
|
||||
assert.NotNil(t, config.Config.RootOfTrust)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user