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

generate: add flag for aks reference values #612

Merged
merged 2 commits into from
Jun 25, 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
13 changes: 13 additions & 0 deletions cli/cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ subcommands.`,
cmd.Flags().StringP("policy", "p", rulesFilename, "path to policy (.rego) file")
cmd.Flags().StringP("settings", "s", settingsFilename, "path to settings (.json) file")
cmd.Flags().StringP("manifest", "m", manifestFilename, "path to manifest (.json) file")
cmd.Flags().String("reference-values", "", "set the default reference values used for attestation (one of: aks)")
davidweisse marked this conversation as resolved.
Show resolved Hide resolved
cmd.Flags().StringArrayP("workload-owner-key", "w", []string{workloadOwnerPEM}, "path to workload owner key (.pem) file")
cmd.Flags().BoolP("disable-updates", "d", false, "prevent further updates of the manifest")
cmd.Flags().String("image-replacements", "", "path to image replacements file")
Expand Down Expand Up @@ -115,6 +116,9 @@ func runGenerate(cmd *cobra.Command, args []string) error {
}

defaultManifest := manifest.Default()
if flags.referenceValues == "aks" {
defaultManifest = manifest.DefaultAKS()
}
defaultManifestData, err := json.MarshalIndent(&defaultManifest, "", " ")
if err != nil {
return fmt.Errorf("marshaling default manifest: %w", err)
Expand Down Expand Up @@ -445,6 +449,7 @@ type generateFlags struct {
policyPath string
settingsPath string
manifestPath string
referenceValues string
workloadOwnerKeys []string
disableUpdates bool
workspaceDir string
Expand All @@ -465,6 +470,13 @@ func parseGenerateFlags(cmd *cobra.Command) (*generateFlags, error) {
if err != nil {
return nil, err
}
referenceValues, err := cmd.Flags().GetString("reference-values")
if err != nil {
return nil, err
}
if !slices.Contains([]string{"", "aks"}, referenceValues) {
return nil, fmt.Errorf("unknown reference values")
}
workloadOwnerKeys, err := cmd.Flags().GetStringArray("workload-owner-key")
if err != nil {
return nil, err
Expand Down Expand Up @@ -507,6 +519,7 @@ func parseGenerateFlags(cmd *cobra.Command) (*generateFlags, error) {
policyPath: policyPath,
settingsPath: settingsPath,
manifestPath: manifestPath,
referenceValues: referenceValues,
workloadOwnerKeys: workloadOwnerKeys,
disableUpdates: disableUpdates,
workspaceDir: workspaceDir,
Expand Down
10 changes: 5 additions & 5 deletions coordinator/internal/authority/authority_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,13 @@ func newManifest(t *testing.T) (*manifest.Manifest, []byte, [][]byte) {
policy := []byte("=== SOME REGO HERE ===")
policyHash := sha256.Sum256(policy)
policyHashHex := manifest.NewHexString(policyHash[:])
mnfst := &manifest.Manifest{
Policies: map[manifest.HexString][]string{policyHashHex: {"test"}},
WorkloadOwnerKeyDigests: []manifest.HexString{keyDigest},
}

mnfst := manifest.DefaultAKS()
mnfst.Policies = map[manifest.HexString][]string{policyHashHex: {"test"}}
mnfst.WorkloadOwnerKeyDigests = []manifest.HexString{keyDigest}
burgerdev marked this conversation as resolved.
Show resolved Hide resolved
mnfstBytes, err := json.Marshal(mnfst)
require.NoError(t, err)
return mnfst, mnfstBytes, [][]byte{policy}
return &mnfst, mnfstBytes, [][]byte{policy}
}

func requireGauge(t *testing.T, reg *prometheus.Registry, val int) {
Expand Down
7 changes: 6 additions & 1 deletion e2e/internal/contrasttest/contrasttest.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,12 @@ func (ct *ContrastTest) Init(t *testing.T, resources []any) {
func (ct *ContrastTest) Generate(t *testing.T) {
require := require.New(t)

args := append(ct.commonArgs(), "--image-replacements", ct.ImageReplacementsFile, path.Join(ct.WorkDir, "resources.yaml"))
args := append(
ct.commonArgs(),
"--image-replacements", ct.ImageReplacementsFile,
"--reference-values", "aks",
path.Join(ct.WorkDir, "resources.yaml"),
)

generate := cmd.NewGenerateCmd()
generate.Flags().String("workspace-dir", "", "") // Make generate aware of root flags
Expand Down
26 changes: 18 additions & 8 deletions internal/manifest/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,25 @@ var trustedMeasurement = "000000000000000000000000000000000000000000000000000000
func Default() Manifest {
return Manifest{
ReferenceValues: ReferenceValues{
SNP: SNPReferenceValues{
MinimumTCB: SNPTCB{
BootloaderVersion: 3,
TEEVersion: 0,
SNPVersion: 8,
MicrocodeVersion: 115,
},
},
TrustedMeasurement: HexString(trustedMeasurement),
},
}
}

// DefaultAKS returns a default manifest with AKS reference values.
func DefaultAKS() Manifest {
mnfst := Default()
mnfst.ReferenceValues.SNP = SNPReferenceValues{
MinimumTCB: SNPTCB{
BootloaderVersion: toPtr(SVN(3)),
TEEVersion: toPtr(SVN(0)),
SNPVersion: toPtr(SVN(8)),
MicrocodeVersion: toPtr(SVN(115)),
},
}
return mnfst
}

func toPtr[T any](t T) *T {
return &t
}
29 changes: 23 additions & 6 deletions internal/manifest/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,18 @@ type SNPReferenceValues struct {

// SNPTCB represents a set of SNP TCB values.
type SNPTCB struct {
BootloaderVersion SVN
TEEVersion SVN
SNPVersion SVN
MicrocodeVersion SVN
BootloaderVersion *SVN
TEEVersion *SVN
SNPVersion *SVN
MicrocodeVersion *SVN
}

// SVN is a SNP secure version number.
type SVN uint8

// UInt8 returns the uint8 value of the SVN.
func (s SVN) UInt8() uint8 {
return uint8(s)
func (s *SVN) UInt8() uint8 {
return uint8(*s)
}

// MarshalJSON marshals the SVN to JSON.
Expand Down Expand Up @@ -137,6 +137,10 @@ func (m *Manifest) SNPValidateOpts() (*validate.Options, error) {
trustedMeasurement = make([]byte, 48)
}

if err = checkNullFields(m.ReferenceValues.SNP.MinimumTCB); err != nil {
return nil, err
}

return &validate.Options{
Measurement: trustedMeasurement,
GuestPolicy: abi.SnpPolicy{
Expand All @@ -159,3 +163,16 @@ func (m *Manifest) SNPValidateOpts() (*validate.Options, error) {
PermitProvisionalFirmware: true,
}, nil
}

func checkNullFields(tcb SNPTCB) error {
if tcb.BootloaderVersion == nil {
return fmt.Errorf("field BootloaderVersion in manifest cannot be empty")
} else if tcb.TEEVersion == nil {
return fmt.Errorf("field TEEVersion in manifest cannot be empty")
} else if tcb.SNPVersion == nil {
return fmt.Errorf("field SNPVersion in manifest cannot be empty")
} else if tcb.MicrocodeVersion == nil {
return fmt.Errorf("field MicrocodeVersion in manifest cannot be empty")
}
return nil
}
61 changes: 61 additions & 0 deletions internal/manifest/manifest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strconv"
"testing"

"github.com/google/go-sev-guest/kds"
"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -145,3 +146,63 @@ func TestPolicy(t *testing.T) {
assert.Error(err)
})
}

func TestSNPValidateOpts(t *testing.T) {
testCases := []struct {
tcb SNPTCB
tm HexString
wantErr bool
}{
{
tcb: SNPTCB{
BootloaderVersion: toPtr(SVN(0)),
TEEVersion: toPtr(SVN(1)),
SNPVersion: toPtr(SVN(2)),
MicrocodeVersion: toPtr(SVN(3)),
},
tm: HexString("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
},
{
tcb: SNPTCB{},
wantErr: true,
},
}

for i, tc := range testCases {
t.Run(strconv.Itoa(i), func(t *testing.T) {
assert := assert.New(t)

mnfst := Manifest{
ReferenceValues: ReferenceValues{
SNP: SNPReferenceValues{MinimumTCB: tc.tcb},
TrustedMeasurement: tc.tm,
},
}

opts, err := mnfst.SNPValidateOpts()
if tc.wantErr {
assert.Error(err)
return
}
assert.NoError(err)

assert.NotNil(tc.tcb.BootloaderVersion)
assert.NotNil(tc.tcb.TEEVersion)
assert.NotNil(tc.tcb.SNPVersion)
assert.NotNil(tc.tcb.MicrocodeVersion)

trustedMeasurement, err := tc.tm.Bytes()
assert.NoError(err)
assert.Equal(trustedMeasurement, opts.Measurement)

tcbParts := kds.TCBParts{
BlSpl: tc.tcb.BootloaderVersion.UInt8(),
TeeSpl: tc.tcb.TEEVersion.UInt8(),
SnpSpl: tc.tcb.SNPVersion.UInt8(),
UcodeSpl: tc.tcb.MicrocodeVersion.UInt8(),
}
assert.Equal(tcbParts, opts.MinimumTCB)
assert.Equal(tcbParts, opts.MinimumLaunchTCB)
})
}
}
1 change: 1 addition & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ generate cli=default_cli:
nix run .#{{ cli }} -- generate \
--workspace-dir ./{{ workspace_dir }} \
--image-replacements ./{{ workspace_dir }}/just.containerlookup \
--reference-values aks \
./{{ workspace_dir }}/deployment/*.yml
duration=$(( $(date +%s) - $t ))
echo "Generated policies in $duration seconds."
Expand Down