2022-09-05 03:06:08 -04:00
/ *
Copyright ( c ) Edgeless Systems GmbH
SPDX - License - Identifier : AGPL - 3.0 - only
* /
2022-11-15 09:40:49 -05:00
package measurements
2022-05-12 04:15:00 -04:00
import (
2023-08-16 04:45:54 -04:00
"bytes"
2022-08-01 03:37:05 -04:00
"context"
2022-11-24 04:57:58 -05:00
"encoding/json"
2022-08-05 09:30:23 -04:00
"io"
2022-08-01 03:37:05 -04:00
"net/http"
"net/url"
"strings"
2022-05-12 04:15:00 -04:00
"testing"
2023-01-02 07:33:56 -05:00
"github.com/siderolabs/talos/pkg/machinery/config/encoder"
2022-05-12 04:15:00 -04:00
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
2022-11-24 04:57:58 -05:00
"gopkg.in/yaml.v3"
2023-05-22 08:59:28 -04:00
2023-06-07 10:16:32 -04:00
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
2023-06-09 09:41:02 -04:00
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
2023-05-22 08:59:28 -04:00
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
2023-05-26 11:49:46 -04:00
"github.com/edgelesssys/constellation/v2/internal/sigstore"
2022-05-12 04:15:00 -04:00
)
2022-11-24 04:57:58 -05:00
func TestMarshal ( t * testing . T ) {
2022-05-12 04:15:00 -04:00
testCases := map [ string ] struct {
2022-11-24 04:57:58 -05:00
m Measurement
wantYAML string
wantJSON string
2022-05-12 04:15:00 -04:00
} {
2022-11-24 04:57:58 -05:00
"measurement" : {
m : Measurement {
2023-03-08 08:13:57 -05:00
Expected : [ ] byte { 253 , 93 , 233 , 223 , 53 , 14 , 59 , 196 , 65 , 10 , 192 , 107 , 191 , 229 , 204 , 222 , 185 , 63 , 83 , 185 , 239 , 81 , 35 , 159 , 117 , 44 , 230 , 157 , 188 , 96 , 15 , 53 } ,
2022-05-12 04:15:00 -04:00
} ,
2022-11-24 04:57:58 -05:00
wantYAML : "expected: \"fd5de9df350e3bc4410ac06bbfe5ccdeb93f53b9ef51239f752ce69dbc600f35\"\nwarnOnly: false" ,
wantJSON : ` { "expected":"fd5de9df350e3bc4410ac06bbfe5ccdeb93f53b9ef51239f752ce69dbc600f35","warnOnly":false} ` ,
2022-05-12 04:15:00 -04:00
} ,
2022-11-24 04:57:58 -05:00
"warn only" : {
m : Measurement {
2023-03-08 08:13:57 -05:00
Expected : [ ] byte { 1 , 2 , 3 , 4 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ,
2023-03-22 06:47:39 -04:00
ValidationOpt : WarnOnly ,
2022-05-12 04:15:00 -04:00
} ,
2022-11-24 04:57:58 -05:00
wantYAML : "expected: \"0102030400000000000000000000000000000000000000000000000000000000\"\nwarnOnly: true" ,
wantJSON : ` { "expected":"0102030400000000000000000000000000000000000000000000000000000000","warnOnly":true} ` ,
2022-05-12 04:15:00 -04:00
} ,
}
for name , tc := range testCases {
t . Run ( name , func ( t * testing . T ) {
assert := assert . New ( t )
require := require . New ( t )
2022-11-24 04:57:58 -05:00
{
// YAML
yaml , err := yaml . Marshal ( tc . m )
require . NoError ( err )
assert . YAMLEq ( tc . wantYAML , string ( yaml ) )
}
{
// JSON
json , err := json . Marshal ( tc . m )
require . NoError ( err )
2022-05-12 04:15:00 -04:00
2022-11-24 04:57:58 -05:00
assert . JSONEq ( tc . wantJSON , string ( json ) )
}
2022-05-12 04:15:00 -04:00
} )
}
}
2022-11-24 04:57:58 -05:00
func TestUnmarshal ( t * testing . T ) {
2022-05-12 04:15:00 -04:00
testCases := map [ string ] struct {
2022-11-24 04:57:58 -05:00
inputYAML string
inputJSON string
wantMeasurements M
wantErr bool
2022-05-12 04:15:00 -04:00
} {
2022-11-24 04:57:58 -05:00
"valid measurements hex" : {
inputYAML : "2:\n expected: \"fd5de9df350e3bc4410ac06bbfe5ccdeb93f53b9ef51239f752ce69dbc600f35\"\n3:\n expected: \"d5a4496d21dec9a5258ddb19c6feb53bb4d3c0463fe607f2488ddf4f1006ef9e\"" ,
inputJSON : ` { "2": { "expected":"fd5de9df350e3bc4410ac06bbfe5ccdeb93f53b9ef51239f752ce69dbc600f35"},"3": { "expected":"d5a4496d21dec9a5258ddb19c6feb53bb4d3c0463fe607f2488ddf4f1006ef9e"}} ` ,
2022-11-15 09:40:49 -05:00
wantMeasurements : M {
2022-11-24 04:57:58 -05:00
2 : {
2023-03-08 08:13:57 -05:00
Expected : [ ] byte { 253 , 93 , 233 , 223 , 53 , 14 , 59 , 196 , 65 , 10 , 192 , 107 , 191 , 229 , 204 , 222 , 185 , 63 , 83 , 185 , 239 , 81 , 35 , 159 , 117 , 44 , 230 , 157 , 188 , 96 , 15 , 53 } ,
2022-11-24 04:57:58 -05:00
} ,
3 : {
2023-03-08 08:13:57 -05:00
Expected : [ ] byte { 213 , 164 , 73 , 109 , 33 , 222 , 201 , 165 , 37 , 141 , 219 , 25 , 198 , 254 , 181 , 59 , 180 , 211 , 192 , 70 , 63 , 230 , 7 , 242 , 72 , 141 , 223 , 79 , 16 , 6 , 239 , 158 } ,
} ,
} ,
} ,
"valid measurements hex 48 bytes" : {
inputYAML : "2:\n expected: \"fd5de9df350e3bc4410ac06bbfe5ccdeb93f53b9ef51239f752ce69dbc600f35fd5de9df350e3bc4410ac06bbfe5ccde\"\n3:\n expected: \"d5a4496d21dec9a5258ddb19c6feb53bb4d3c0463fe607f2488ddf4f1006ef9efd5de9df350e3bc4410ac06bbfe5ccde\"" ,
inputJSON : ` { "2": { "expected":"fd5de9df350e3bc4410ac06bbfe5ccdeb93f53b9ef51239f752ce69dbc600f35fd5de9df350e3bc4410ac06bbfe5ccde"},"3": { "expected":"d5a4496d21dec9a5258ddb19c6feb53bb4d3c0463fe607f2488ddf4f1006ef9efd5de9df350e3bc4410ac06bbfe5ccde"}} ` ,
wantMeasurements : M {
2 : {
Expected : [ ] byte { 253 , 93 , 233 , 223 , 53 , 14 , 59 , 196 , 65 , 10 , 192 , 107 , 191 , 229 , 204 , 222 , 185 , 63 , 83 , 185 , 239 , 81 , 35 , 159 , 117 , 44 , 230 , 157 , 188 , 96 , 15 , 53 , 253 , 93 , 233 , 223 , 53 , 14 , 59 , 196 , 65 , 10 , 192 , 107 , 191 , 229 , 204 , 222 } ,
} ,
3 : {
Expected : [ ] byte { 213 , 164 , 73 , 109 , 33 , 222 , 201 , 165 , 37 , 141 , 219 , 25 , 198 , 254 , 181 , 59 , 180 , 211 , 192 , 70 , 63 , 230 , 7 , 242 , 72 , 141 , 223 , 79 , 16 , 6 , 239 , 158 , 253 , 93 , 233 , 223 , 53 , 14 , 59 , 196 , 65 , 10 , 192 , 107 , 191 , 229 , 204 , 222 } ,
2022-11-24 04:57:58 -05:00
} ,
2022-05-12 04:15:00 -04:00
} ,
} ,
"empty bytes" : {
2023-06-01 06:33:06 -04:00
inputYAML : "2:\n expected: \"0000000000000000000000000000000000000000000000000000000000000000\"\n3:\n expected: \"0102030400000000000000000000000000000000000000000000000000000000\"" ,
inputJSON : ` { "2": { "expected":"0000000000000000000000000000000000000000000000000000000000000000"},"3": { "expected":"0102030400000000000000000000000000000000000000000000000000000000"}} ` ,
2022-11-15 09:40:49 -05:00
wantMeasurements : M {
2022-11-24 04:57:58 -05:00
2 : {
2023-03-08 08:13:57 -05:00
Expected : [ ] byte { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ,
2022-11-24 04:57:58 -05:00
} ,
3 : {
2023-03-08 08:13:57 -05:00
Expected : [ ] byte { 1 , 2 , 3 , 4 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ,
2022-11-24 04:57:58 -05:00
} ,
2022-05-12 04:15:00 -04:00
} ,
} ,
"invalid base64" : {
2022-11-24 04:57:58 -05:00
inputYAML : "2:\n expected: \"This is not base64\"\n3:\n expected: \"AQIDBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\"" ,
inputJSON : ` { "2": { "expected":"This is not base64"},"3": { "expected":"AQIDBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="}} ` ,
wantErr : true ,
2022-05-12 04:15:00 -04:00
} ,
2022-11-24 04:57:58 -05:00
"invalid length hex" : {
inputYAML : "2:\n expected: \"fd5de9df350e3bc4410ac06bbfe5ccdeb93f53b9ef\"\n3:\n expected: \"d5a4496d21dec9a5258ddb19c6feb53bb4d3c0463f\"" ,
inputJSON : ` { "2": { "expected":"fd5de9df350e3bc4410ac06bbfe5ccdeb93f53b9ef"},"3": { "expected":"d5a4496d21dec9a5258ddb19c6feb53bb4d3c0463f"}} ` ,
wantErr : true ,
} ,
2023-03-08 08:13:57 -05:00
"mixed length hex" : {
inputYAML : "2:\n expected: \"fd5de9df350e3bc4410ac06bbfe5ccdeb93f53b9ef51239f752ce69dbc600f35fd5de9df350e3bc4410ac06bbfe5ccde\"\n3:\n expected: \"d5a4496d21dec9a5258ddb19c6feb53bb4d3c0463fe607f2488ddf4f1006ef9e\"" ,
inputJSON : ` { "2": { "expected":"fd5de9df350e3bc4410ac06bbfe5ccdeb93f53b9ef51239f752ce69dbc600f35fd5de9df350e3bc4410ac06bbfe5ccde"},"3": { "expected":"d5a4496d21dec9a5258ddb19c6feb53bb4d3c0463fe607f2488ddf4f1006ef9e"}} ` ,
wantErr : true ,
} ,
2022-11-24 04:57:58 -05:00
"invalid length base64" : {
inputYAML : "2:\n expected: \"AA==\"\n3:\n expected: \"AQIDBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\"" ,
inputJSON : ` { "2": { "expected":"AA=="},"3": { "expected":"AQIDBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="}} ` ,
wantErr : true ,
} ,
"invalid format" : {
inputYAML : "1:\n expected:\n someKey: 12\n anotherKey: 34" ,
inputJSON : ` { "1": { "expected": { "someKey":12,"anotherKey":34}}} ` ,
wantErr : true ,
2022-05-12 04:15:00 -04:00
} ,
}
for name , tc := range testCases {
t . Run ( name , func ( t * testing . T ) {
assert := assert . New ( t )
require := require . New ( t )
2022-11-24 04:57:58 -05:00
{
// YAML
var m M
err := yaml . Unmarshal ( [ ] byte ( tc . inputYAML ) , & m )
if tc . wantErr {
assert . Error ( err , "yaml.Unmarshal should have failed" )
} else {
require . NoError ( err , "yaml.Unmarshal failed" )
assert . Equal ( tc . wantMeasurements , m )
2022-05-12 04:15:00 -04:00
}
2022-11-24 04:57:58 -05:00
}
2022-05-12 04:15:00 -04:00
2022-11-24 04:57:58 -05:00
{
// JSON
var m M
err := json . Unmarshal ( [ ] byte ( tc . inputJSON ) , & m )
if tc . wantErr {
assert . Error ( err , "json.Unmarshal should have failed" )
} else {
require . NoError ( err , "json.Unmarshal failed" )
assert . Equal ( tc . wantMeasurements , m )
}
2022-05-12 04:15:00 -04:00
}
} )
}
}
2022-08-01 03:37:05 -04:00
2022-11-28 05:09:39 -05:00
func TestEncodeM ( t * testing . T ) {
testCases := map [ string ] struct {
m M
want string
} {
"basic" : {
m : M {
2023-03-10 05:33:06 -05:00
1 : WithAllBytes ( 1 , false , PCRMeasurementLength ) ,
2 : WithAllBytes ( 2 , WarnOnly , PCRMeasurementLength ) ,
2022-11-28 05:09:39 -05:00
} ,
want : ` 1 :
expected : "0101010101010101010101010101010101010101010101010101010101010101"
warnOnly : false
2 :
expected : "0202020202020202020202020202020202020202020202020202020202020202"
warnOnly : true
` ,
} ,
"output is sorted" : {
m : M {
2023-03-10 05:33:06 -05:00
3 : WithAllBytes ( 0 , false , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0 , false , PCRMeasurementLength ) ,
11 : WithAllBytes ( 0 , false , PCRMeasurementLength ) ,
2 : WithAllBytes ( 0 , false , PCRMeasurementLength ) ,
2022-11-28 05:09:39 -05:00
} ,
want : ` 1 :
expected : "0000000000000000000000000000000000000000000000000000000000000000"
warnOnly : false
2 :
expected : "0000000000000000000000000000000000000000000000000000000000000000"
warnOnly : false
3 :
expected : "0000000000000000000000000000000000000000000000000000000000000000"
warnOnly : false
11 :
expected : "0000000000000000000000000000000000000000000000000000000000000000"
warnOnly : false
` ,
} ,
}
for name , tc := range testCases {
t . Run ( name , func ( t * testing . T ) {
assert := assert . New ( t )
require := require . New ( t )
encoded , err := encoder . NewEncoder ( tc . m ) . Encode ( )
require . NoError ( err )
assert . Equal ( tc . want , string ( encoded ) )
} )
}
}
2022-08-01 03:37:05 -04:00
func TestMeasurementsCopyFrom ( t * testing . T ) {
testCases := map [ string ] struct {
2022-11-15 09:40:49 -05:00
current M
newMeasurements M
wantMeasurements M
2022-08-01 03:37:05 -04:00
} {
"add to empty" : {
2022-11-15 09:40:49 -05:00
current : M { } ,
newMeasurements : M {
2023-03-10 05:33:06 -05:00
1 : WithAllBytes ( 0x00 , WarnOnly , PCRMeasurementLength ) ,
2 : WithAllBytes ( 0x01 , WarnOnly , PCRMeasurementLength ) ,
3 : WithAllBytes ( 0x02 , WarnOnly , PCRMeasurementLength ) ,
2022-08-01 03:37:05 -04:00
} ,
2022-11-15 09:40:49 -05:00
wantMeasurements : M {
2023-03-10 05:33:06 -05:00
1 : WithAllBytes ( 0x00 , WarnOnly , PCRMeasurementLength ) ,
2 : WithAllBytes ( 0x01 , WarnOnly , PCRMeasurementLength ) ,
3 : WithAllBytes ( 0x02 , WarnOnly , PCRMeasurementLength ) ,
2022-08-01 03:37:05 -04:00
} ,
} ,
"keep existing" : {
2022-11-15 09:40:49 -05:00
current : M {
2023-03-10 05:33:06 -05:00
4 : WithAllBytes ( 0x01 , Enforce , PCRMeasurementLength ) ,
5 : WithAllBytes ( 0x02 , WarnOnly , PCRMeasurementLength ) ,
2022-08-01 03:37:05 -04:00
} ,
2022-11-15 09:40:49 -05:00
newMeasurements : M {
2023-03-10 05:33:06 -05:00
1 : WithAllBytes ( 0x00 , WarnOnly , PCRMeasurementLength ) ,
2 : WithAllBytes ( 0x01 , WarnOnly , PCRMeasurementLength ) ,
3 : WithAllBytes ( 0x02 , WarnOnly , PCRMeasurementLength ) ,
2022-08-01 03:37:05 -04:00
} ,
2022-11-15 09:40:49 -05:00
wantMeasurements : M {
2023-03-10 05:33:06 -05:00
1 : WithAllBytes ( 0x00 , WarnOnly , PCRMeasurementLength ) ,
2 : WithAllBytes ( 0x01 , WarnOnly , PCRMeasurementLength ) ,
3 : WithAllBytes ( 0x02 , WarnOnly , PCRMeasurementLength ) ,
4 : WithAllBytes ( 0x01 , Enforce , PCRMeasurementLength ) ,
5 : WithAllBytes ( 0x02 , WarnOnly , PCRMeasurementLength ) ,
2022-08-01 03:37:05 -04:00
} ,
} ,
"overwrite existing" : {
2022-11-15 09:40:49 -05:00
current : M {
2023-03-10 05:33:06 -05:00
2 : WithAllBytes ( 0x04 , Enforce , PCRMeasurementLength ) ,
3 : WithAllBytes ( 0x05 , Enforce , PCRMeasurementLength ) ,
2022-08-01 03:37:05 -04:00
} ,
2022-11-15 09:40:49 -05:00
newMeasurements : M {
2023-03-10 05:33:06 -05:00
1 : WithAllBytes ( 0x00 , WarnOnly , PCRMeasurementLength ) ,
2 : WithAllBytes ( 0x01 , WarnOnly , PCRMeasurementLength ) ,
3 : WithAllBytes ( 0x02 , WarnOnly , PCRMeasurementLength ) ,
2022-08-01 03:37:05 -04:00
} ,
2022-11-15 09:40:49 -05:00
wantMeasurements : M {
2023-03-10 05:33:06 -05:00
1 : WithAllBytes ( 0x00 , WarnOnly , PCRMeasurementLength ) ,
2 : WithAllBytes ( 0x01 , WarnOnly , PCRMeasurementLength ) ,
3 : WithAllBytes ( 0x02 , WarnOnly , PCRMeasurementLength ) ,
2022-08-01 03:37:05 -04:00
} ,
} ,
}
for name , tc := range testCases {
t . Run ( name , func ( t * testing . T ) {
assert := assert . New ( t )
tc . current . CopyFrom ( tc . newMeasurements )
assert . Equal ( tc . wantMeasurements , tc . current )
} )
}
}
// roundTripFunc .
type roundTripFunc func ( req * http . Request ) * http . Response
// RoundTrip .
func ( f roundTripFunc ) RoundTrip ( req * http . Request ) ( * http . Response , error ) {
return f ( req ) , nil
}
// newTestClient returns *http.Client with Transport replaced to avoid making real calls.
func newTestClient ( fn roundTripFunc ) * http . Client {
return & http . Client {
Transport : fn ,
}
}
func urlMustParse ( raw string ) * url . URL {
parsed , _ := url . Parse ( raw )
return parsed
}
func TestMeasurementsFetchAndVerify ( t * testing . T ) {
2023-03-22 06:47:39 -04:00
// Cosign private key used to sign the
2022-11-24 04:57:58 -05:00
// Generated with: cosign generate-key-pair
// Password left empty.
//
// -----BEGIN ENCRYPTED COSIGN PRIVATE KEY-----
// eyJrZGYiOnsibmFtZSI6InNjcnlwdCIsInBhcmFtcyI6eyJOIjozMjc2OCwiciI6
// OCwicCI6MX0sInNhbHQiOiJlRHVYMWRQMGtIWVRnK0xkbjcxM0tjbFVJaU92eFVX
// VXgvNi9BbitFVk5BPSJ9LCJjaXBoZXIiOnsibmFtZSI6Im5hY2wvc2VjcmV0Ym94
// Iiwibm9uY2UiOiJwaWhLL2txNmFXa2hqSVVHR3RVUzhTVkdHTDNIWWp4TCJ9LCJj
// aXBoZXJ0ZXh0Ijoidm81SHVWRVFWcUZ2WFlQTTVPaTVaWHM5a255bndZU2dvcyth
// VklIeHcrOGFPamNZNEtvVjVmL3lHRHR0K3BHV2toanJPR1FLOWdBbmtsazFpQ0c5
// a2czUXpPQTZsU2JRaHgvZlowRVRZQ0hLeElncEdPRVRyTDlDenZDemhPZXVSOXJ6
// TDcvRjBBVy9vUDVqZXR3dmJMNmQxOEhjck9kWE8yVmYxY2w0YzNLZjVRcnFSZzlN
// dlRxQWFsNXJCNHNpY1JaMVhpUUJjb0YwNHc9PSJ9
// -----END ENCRYPTED COSIGN PRIVATE KEY-----
2022-11-28 04:27:33 -05:00
cosignPublicKey := [ ] byte ( "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEu78QgxOOcao6U91CSzEXxrKhvFTt\nJHNy+eX6EMePtDm8CnDF9HSwnTlD0itGJ/XHPQA5YX10fJAqI1y+ehlFMw==\n-----END PUBLIC KEY-----" )
2022-11-24 04:57:58 -05:00
2023-08-01 10:48:13 -04:00
v1Test , err := versionsapi . NewVersion ( "-" , "stable" , "v1.0.0-test" , versionsapi . VersionKindImage )
require . NoError ( t , err )
v1AnotherImage , err := versionsapi . NewVersion ( "-" , "stable" , "v1.0.0-another-image" , versionsapi . VersionKindImage )
require . NoError ( t , err )
2022-08-01 03:37:05 -04:00
testCases := map [ string ] struct {
measurements string
2023-05-22 08:59:28 -04:00
csp cloudprovider . Provider
attestationVariant variant . Variant
imageVersion versionsapi . Version
2022-08-01 03:37:05 -04:00
measurementsStatus int
signature string
signatureStatus int
2022-11-15 09:40:49 -05:00
wantMeasurements M
2022-10-11 07:57:52 -04:00
wantSHA string
2022-08-01 03:37:05 -04:00
wantError bool
} {
2022-11-24 04:57:58 -05:00
"json measurements" : {
2023-05-22 08:59:28 -04:00
measurements : ` { "version":"v1.0.0-test","ref":"-","stream":"stable","list":[ { "csp":"Unknown","attestationVariant":"dummy","measurements": { "0": { "expected":"0000000000000000000000000000000000000000000000000000000000000000","warnOnly":false}}}]} ` ,
csp : cloudprovider . Unknown ,
2023-08-01 10:48:13 -04:00
imageVersion : v1Test ,
2022-11-24 04:57:58 -05:00
measurementsStatus : http . StatusOK ,
2023-05-22 08:59:28 -04:00
signature : "MEUCIHuW2420EqN4Kj6OEaVMmufH7d01vyR1J+SWg8H4elyBAiEA1Ki5Hfq0iI70qpViYbrTFrd8e840NjtdAxGqJKiJgbA=" ,
2022-11-24 04:57:58 -05:00
signatureStatus : http . StatusOK ,
wantMeasurements : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
2022-11-24 04:57:58 -05:00
} ,
2023-05-22 08:59:28 -04:00
wantSHA : "7269a1e8c6a379b86af605f993352df1d4a289bbf79fe655fd78338bd7549d52" ,
2022-11-24 04:57:58 -05:00
} ,
2022-08-01 03:37:05 -04:00
"404 measurements" : {
2023-05-22 08:59:28 -04:00
measurements : ` { "version":"v1.0.0-test","ref":"-","stream":"stable","list":[ { "csp":"Unknown","attestationVariant":"dummy","measurements": { "0": { "expected":"0000000000000000000000000000000000000000000000000000000000000000","warnOnly":false}}}]} ` ,
csp : cloudprovider . Unknown ,
2023-08-01 10:48:13 -04:00
imageVersion : v1Test ,
2022-08-01 03:37:05 -04:00
measurementsStatus : http . StatusNotFound ,
2023-05-22 08:59:28 -04:00
signature : "MEUCIHuW2420EqN4Kj6OEaVMmufH7d01vyR1J+SWg8H4elyBAiEA1Ki5Hfq0iI70qpViYbrTFrd8e840NjtdAxGqJKiJgbA=" ,
2022-08-01 03:37:05 -04:00
signatureStatus : http . StatusOK ,
wantError : true ,
} ,
"404 signature" : {
2023-05-22 08:59:28 -04:00
measurements : ` { "version":"v1.0.0-test","ref":"-","stream":"stable","list":[ { "csp":"Unknown","attestationVariant":"dummy","measurements": { "0": { "expected":"0000000000000000000000000000000000000000000000000000000000000000","warnOnly":false}}}]} ` ,
csp : cloudprovider . Unknown ,
2023-08-01 10:48:13 -04:00
imageVersion : v1Test ,
2022-08-01 03:37:05 -04:00
measurementsStatus : http . StatusOK ,
2023-05-22 08:59:28 -04:00
signature : "MEUCIHuW2420EqN4Kj6OEaVMmufH7d01vyR1J+SWg8H4elyBAiEA1Ki5Hfq0iI70qpViYbrTFrd8e840NjtdAxGqJKiJgbA=" ,
2022-08-01 03:37:05 -04:00
signatureStatus : http . StatusNotFound ,
wantError : true ,
} ,
"broken signature" : {
2023-05-22 08:59:28 -04:00
measurements : ` { "version":"v1.0.0-test","ref":"-","stream":"stable","list":[ { "csp":"Unknown","attestationVariant":"dummy","measurements": { "0": { "expected":"0000000000000000000000000000000000000000000000000000000000000000","warnOnly":false}}}]} ` ,
csp : cloudprovider . Unknown ,
2023-08-01 10:48:13 -04:00
imageVersion : v1Test ,
2022-08-01 03:37:05 -04:00
measurementsStatus : http . StatusOK ,
2022-11-28 04:27:33 -05:00
signature : "AAAAAAA1RR91pWPw1BMWXTSmTBHg/JtfKerbZNQ9PJTWDdW0sgIhANQbETJGb67qzQmMVmcq007VUFbHRMtYWKZeeyRf0gVa" ,
signatureStatus : http . StatusOK ,
wantError : true ,
} ,
"metadata CSP mismatch" : {
2023-05-22 08:59:28 -04:00
measurements : ` { "version":"v1.0.0-test","ref":"-","stream":"stable","list":[ { "csp":"Unknown","attestationVariant":"dummy","measurements": { "0": { "expected":"0000000000000000000000000000000000000000000000000000000000000000","warnOnly":false}}}]} ` ,
csp : cloudprovider . GCP ,
2023-08-01 10:48:13 -04:00
imageVersion : v1Test ,
2022-11-28 04:27:33 -05:00
measurementsStatus : http . StatusOK ,
2023-05-22 08:59:28 -04:00
signature : "MEUCIHuW2420EqN4Kj6OEaVMmufH7d01vyR1J+SWg8H4elyBAiEA1Ki5Hfq0iI70qpViYbrTFrd8e840NjtdAxGqJKiJgbA=" ,
2022-11-28 04:27:33 -05:00
signatureStatus : http . StatusOK ,
wantError : true ,
} ,
"metadata image mismatch" : {
2023-05-22 08:59:28 -04:00
measurements : ` { "version":"v1.0.0-test","ref":"-","stream":"stable","list":[ { "csp":"Unknown","attestationVariant":"dummy","measurements": { "0": { "expected":"0000000000000000000000000000000000000000000000000000000000000000","warnOnly":false}}}]} ` ,
csp : cloudprovider . Unknown ,
2023-08-01 10:48:13 -04:00
imageVersion : v1AnotherImage ,
2022-11-28 04:27:33 -05:00
measurementsStatus : http . StatusOK ,
2023-05-22 08:59:28 -04:00
signature : "MEUCIHuW2420EqN4Kj6OEaVMmufH7d01vyR1J+SWg8H4elyBAiEA1Ki5Hfq0iI70qpViYbrTFrd8e840NjtdAxGqJKiJgbA=" ,
2022-08-01 03:37:05 -04:00
signatureStatus : http . StatusOK ,
wantError : true ,
} ,
2023-05-22 08:59:28 -04:00
"not json" : {
2022-08-01 03:37:05 -04:00
measurements : "This is some content to be signed!\n" ,
2023-05-22 08:59:28 -04:00
csp : cloudprovider . Unknown ,
2023-08-01 10:48:13 -04:00
imageVersion : v1Test ,
2022-08-01 03:37:05 -04:00
measurementsStatus : http . StatusOK ,
2022-11-24 04:57:58 -05:00
signature : "MEUCIQCGA/lSu5qCJgNNvgMaTKJ9rj6vQMecUDaQo3ukaiAfUgIgWoxXRoDKLY9naN7YgxokM7r2fwnyYk3M2WKJJO1g6yo=" ,
2022-08-01 03:37:05 -04:00
signatureStatus : http . StatusOK ,
wantError : true ,
} ,
}
2023-03-22 06:47:39 -04:00
measurementsURL := urlMustParse ( "https://somesite.com/yaml" )
signatureURL := urlMustParse ( "https://somesite.com/yaml.sig" )
2022-08-01 03:37:05 -04:00
for name , tc := range testCases {
t . Run ( name , func ( t * testing . T ) {
assert := assert . New ( t )
2023-08-01 10:48:13 -04:00
require := require . New ( t )
2022-08-01 03:37:05 -04:00
2023-05-22 08:59:28 -04:00
if tc . attestationVariant == nil {
tc . attestationVariant = variant . Dummy { }
}
2022-08-01 03:37:05 -04:00
client := newTestClient ( func ( req * http . Request ) * http . Response {
if req . URL . String ( ) == measurementsURL . String ( ) {
return & http . Response {
StatusCode : tc . measurementsStatus ,
2022-08-05 09:30:23 -04:00
Body : io . NopCloser ( strings . NewReader ( tc . measurements ) ) ,
2022-08-01 03:37:05 -04:00
Header : make ( http . Header ) ,
}
}
if req . URL . String ( ) == signatureURL . String ( ) {
return & http . Response {
StatusCode : tc . signatureStatus ,
2022-08-05 09:30:23 -04:00
Body : io . NopCloser ( strings . NewReader ( tc . signature ) ) ,
2022-08-01 03:37:05 -04:00
Header : make ( http . Header ) ,
}
}
return & http . Response {
StatusCode : http . StatusNotFound ,
2022-08-05 09:30:23 -04:00
Body : io . NopCloser ( strings . NewReader ( "Not found." ) ) ,
2022-08-01 03:37:05 -04:00
Header : make ( http . Header ) ,
}
} )
2022-11-15 09:40:49 -05:00
m := M { }
2022-11-28 04:27:33 -05:00
2023-08-01 10:48:13 -04:00
verifier , err := sigstore . NewCosignVerifier ( cosignPublicKey )
require . NoError ( err )
2023-05-26 11:49:46 -04:00
hash , err := m . fetchAndVerify (
2023-08-01 10:48:13 -04:00
context . Background ( ) , client , verifier ,
2022-11-28 04:27:33 -05:00
measurementsURL , signatureURL ,
2023-05-22 08:59:28 -04:00
tc . imageVersion ,
tc . csp ,
tc . attestationVariant ,
2022-11-28 04:27:33 -05:00
)
2022-08-01 03:37:05 -04:00
if tc . wantError {
assert . Error ( err )
return
}
2022-10-11 07:57:52 -04:00
assert . Equal ( tc . wantSHA , hash )
2022-08-01 03:37:05 -04:00
assert . NoError ( err )
assert . EqualValues ( tc . wantMeasurements , m )
} )
}
}
2022-11-15 09:40:49 -05:00
2022-11-24 04:57:58 -05:00
func TestGetEnforced ( t * testing . T ) {
2022-11-15 09:40:49 -05:00
testCases := map [ string ] struct {
2022-11-24 04:57:58 -05:00
input M
want map [ uint32 ] struct { }
2022-11-15 09:40:49 -05:00
} {
2022-11-24 04:57:58 -05:00
"only warnings" : {
input : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0x00 , WarnOnly , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0x01 , WarnOnly , PCRMeasurementLength ) ,
2022-11-24 04:57:58 -05:00
} ,
want : map [ uint32 ] struct { } { } ,
} ,
"all enforced" : {
input : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0x01 , Enforce , PCRMeasurementLength ) ,
2022-11-24 04:57:58 -05:00
} ,
want : map [ uint32 ] struct { } {
0 : { } ,
1 : { } ,
} ,
} ,
"mixed" : {
input : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0x01 , WarnOnly , PCRMeasurementLength ) ,
2 : WithAllBytes ( 0x02 , Enforce , PCRMeasurementLength ) ,
2022-11-24 04:57:58 -05:00
} ,
want : map [ uint32 ] struct { } {
0 : { } ,
2 : { } ,
} ,
} ,
}
for name , tc := range testCases {
t . Run ( name , func ( t * testing . T ) {
assert := assert . New ( t )
got := tc . input . GetEnforced ( )
enforced := map [ uint32 ] struct { } { }
for _ , id := range got {
enforced [ id ] = struct { } { }
}
assert . Equal ( tc . want , enforced )
} )
}
}
func TestSetEnforced ( t * testing . T ) {
testCases := map [ string ] struct {
input M
enforced [ ] uint32
wantM M
wantErr bool
} {
"no enforced measurements" : {
input : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0x01 , Enforce , PCRMeasurementLength ) ,
2022-11-24 04:57:58 -05:00
} ,
enforced : [ ] uint32 { } ,
wantM : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0x00 , WarnOnly , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0x01 , WarnOnly , PCRMeasurementLength ) ,
2022-11-24 04:57:58 -05:00
} ,
} ,
"all enforced measurements" : {
input : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0x01 , Enforce , PCRMeasurementLength ) ,
2022-11-24 04:57:58 -05:00
} ,
enforced : [ ] uint32 { 0 , 1 } ,
wantM : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0x01 , Enforce , PCRMeasurementLength ) ,
2022-11-24 04:57:58 -05:00
} ,
} ,
"mixed" : {
input : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0x01 , Enforce , PCRMeasurementLength ) ,
2 : WithAllBytes ( 0x02 , Enforce , PCRMeasurementLength ) ,
3 : WithAllBytes ( 0x03 , Enforce , PCRMeasurementLength ) ,
2022-11-24 04:57:58 -05:00
} ,
enforced : [ ] uint32 { 0 , 2 } ,
wantM : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0x01 , WarnOnly , PCRMeasurementLength ) ,
2 : WithAllBytes ( 0x02 , Enforce , PCRMeasurementLength ) ,
3 : WithAllBytes ( 0x03 , WarnOnly , PCRMeasurementLength ) ,
2022-11-24 04:57:58 -05:00
} ,
} ,
"warn only to enforced" : {
input : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0x00 , WarnOnly , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0x01 , WarnOnly , PCRMeasurementLength ) ,
2022-11-24 04:57:58 -05:00
} ,
enforced : [ ] uint32 { 0 , 1 } ,
wantM : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0x01 , Enforce , PCRMeasurementLength ) ,
2022-11-24 04:57:58 -05:00
} ,
} ,
"more enforced than measurements" : {
input : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0x00 , WarnOnly , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0x01 , WarnOnly , PCRMeasurementLength ) ,
2022-11-24 04:57:58 -05:00
} ,
enforced : [ ] uint32 { 0 , 1 , 2 } ,
wantErr : true ,
} ,
}
for name , tc := range testCases {
t . Run ( name , func ( t * testing . T ) {
assert := assert . New ( t )
err := tc . input . SetEnforced ( tc . enforced )
if tc . wantErr {
assert . Error ( err )
return
}
assert . NoError ( err )
assert . True ( tc . input . EqualTo ( tc . wantM ) )
} )
}
}
func TestWithAllBytes ( t * testing . T ) {
testCases := map [ string ] struct {
b byte
2023-03-22 06:47:39 -04:00
warnOnly MeasurementValidationOption
2022-11-24 04:57:58 -05:00
wantMeasurement Measurement
} {
"0x00 warnOnly" : {
b : 0x00 ,
2023-03-10 05:33:06 -05:00
warnOnly : WarnOnly ,
2022-11-24 04:57:58 -05:00
wantMeasurement : Measurement {
2023-03-08 08:13:57 -05:00
Expected : [ ] byte { 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ,
2023-03-22 06:47:39 -04:00
ValidationOpt : WarnOnly ,
2022-11-24 04:57:58 -05:00
} ,
} ,
2022-11-15 09:40:49 -05:00
"0x00" : {
2022-11-24 04:57:58 -05:00
b : 0x00 ,
2023-03-10 05:33:06 -05:00
warnOnly : Enforce ,
2022-11-24 04:57:58 -05:00
wantMeasurement : Measurement {
2023-03-08 08:13:57 -05:00
Expected : [ ] byte { 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ,
2023-03-22 06:47:39 -04:00
ValidationOpt : Enforce ,
2022-11-24 04:57:58 -05:00
} ,
} ,
"0x01 warnOnly" : {
b : 0x01 ,
2023-03-10 05:33:06 -05:00
warnOnly : WarnOnly ,
2022-11-24 04:57:58 -05:00
wantMeasurement : Measurement {
2023-03-08 08:13:57 -05:00
Expected : [ ] byte { 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 } ,
2023-03-22 06:47:39 -04:00
ValidationOpt : WarnOnly ,
2022-11-24 04:57:58 -05:00
} ,
2022-11-15 09:40:49 -05:00
} ,
"0x01" : {
2022-11-24 04:57:58 -05:00
b : 0x01 ,
2023-03-10 05:33:06 -05:00
warnOnly : Enforce ,
2022-11-24 04:57:58 -05:00
wantMeasurement : Measurement {
2023-03-08 08:13:57 -05:00
Expected : [ ] byte { 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 } ,
2023-03-22 06:47:39 -04:00
ValidationOpt : Enforce ,
2022-11-24 04:57:58 -05:00
} ,
} ,
"0xFF warnOnly" : {
b : 0xFF ,
2023-03-10 05:33:06 -05:00
warnOnly : WarnOnly ,
2022-11-24 04:57:58 -05:00
wantMeasurement : Measurement {
2023-03-08 08:13:57 -05:00
Expected : [ ] byte { 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF } ,
2023-03-22 06:47:39 -04:00
ValidationOpt : WarnOnly ,
2022-11-24 04:57:58 -05:00
} ,
2022-11-15 09:40:49 -05:00
} ,
"0xFF" : {
2022-11-24 04:57:58 -05:00
b : 0xFF ,
2023-03-10 05:33:06 -05:00
warnOnly : Enforce ,
2022-11-24 04:57:58 -05:00
wantMeasurement : Measurement {
2023-03-08 08:13:57 -05:00
Expected : [ ] byte { 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF } ,
2023-03-22 06:47:39 -04:00
ValidationOpt : Enforce ,
2022-11-24 04:57:58 -05:00
} ,
2022-11-15 09:40:49 -05:00
} ,
}
for name , tc := range testCases {
t . Run ( name , func ( t * testing . T ) {
assert := assert . New ( t )
2023-03-10 05:33:06 -05:00
measurement := WithAllBytes ( tc . b , tc . warnOnly , PCRMeasurementLength )
2022-11-24 04:57:58 -05:00
assert . Equal ( tc . wantMeasurement , measurement )
2022-11-15 09:40:49 -05:00
} )
}
}
func TestEqualTo ( t * testing . T ) {
testCases := map [ string ] struct {
given M
other M
wantEqual bool
} {
"same values" : {
given : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0xFF , Enforce , PCRMeasurementLength ) ,
2022-11-15 09:40:49 -05:00
} ,
other : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0xFF , Enforce , PCRMeasurementLength ) ,
2022-11-15 09:40:49 -05:00
} ,
wantEqual : true ,
} ,
"different number of elements" : {
given : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0xFF , Enforce , PCRMeasurementLength ) ,
2022-11-15 09:40:49 -05:00
} ,
other : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
2022-11-15 09:40:49 -05:00
} ,
wantEqual : false ,
} ,
"different values" : {
given : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0xFF , Enforce , PCRMeasurementLength ) ,
2022-11-24 04:57:58 -05:00
} ,
other : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0xFF , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
2022-11-24 04:57:58 -05:00
} ,
wantEqual : false ,
} ,
"different warn settings" : {
given : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0xFF , Enforce , PCRMeasurementLength ) ,
2022-11-15 09:40:49 -05:00
} ,
other : M {
2023-03-10 05:33:06 -05:00
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0xFF , WarnOnly , PCRMeasurementLength ) ,
2022-11-15 09:40:49 -05:00
} ,
wantEqual : false ,
} ,
}
for name , tc := range testCases {
t . Run ( name , func ( t * testing . T ) {
assert := assert . New ( t )
if tc . wantEqual {
assert . True ( tc . given . EqualTo ( tc . other ) )
} else {
assert . False ( tc . given . EqualTo ( tc . other ) )
}
} )
}
}
2023-05-23 05:13:52 -04:00
func TestMergeImageMeasurementsV2 ( t * testing . T ) {
testCases := map [ string ] struct {
measurements [ ] ImageMeasurementsV2
wantMeasurements ImageMeasurementsV2
wantErr bool
} {
"only one element" : {
measurements : [ ] ImageMeasurementsV2 {
{
Ref : "test-ref" ,
Stream : "nightly" ,
Version : "v1.0.0" ,
List : [ ] ImageMeasurementsV2Entry {
{
CSP : cloudprovider . AWS ,
AttestationVariant : "aws-nitro-tpm" ,
Measurements : M {
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
} ,
} ,
} ,
} ,
} ,
wantMeasurements : ImageMeasurementsV2 {
Ref : "test-ref" ,
Stream : "nightly" ,
Version : "v1.0.0" ,
List : [ ] ImageMeasurementsV2Entry {
{
CSP : cloudprovider . AWS ,
AttestationVariant : "aws-nitro-tpm" ,
Measurements : M {
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
} ,
} ,
} ,
} ,
} ,
"valid measurements" : {
measurements : [ ] ImageMeasurementsV2 {
{
Ref : "test-ref" ,
Stream : "nightly" ,
Version : "v1.0.0" ,
List : [ ] ImageMeasurementsV2Entry {
{
CSP : cloudprovider . AWS ,
AttestationVariant : "aws-nitro-tpm" ,
Measurements : M {
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
} ,
} ,
} ,
} ,
{
Ref : "test-ref" ,
Stream : "nightly" ,
Version : "v1.0.0" ,
List : [ ] ImageMeasurementsV2Entry {
{
CSP : cloudprovider . GCP ,
AttestationVariant : "gcp-sev-es" ,
Measurements : M {
1 : WithAllBytes ( 0x11 , Enforce , PCRMeasurementLength ) ,
} ,
} ,
} ,
} ,
} ,
wantMeasurements : ImageMeasurementsV2 {
Ref : "test-ref" ,
Stream : "nightly" ,
Version : "v1.0.0" ,
List : [ ] ImageMeasurementsV2Entry {
{
CSP : cloudprovider . AWS ,
AttestationVariant : "aws-nitro-tpm" ,
Measurements : M {
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
} ,
} ,
{
CSP : cloudprovider . GCP ,
AttestationVariant : "gcp-sev-es" ,
Measurements : M {
1 : WithAllBytes ( 0x11 , Enforce , PCRMeasurementLength ) ,
} ,
} ,
} ,
} ,
} ,
"sorting" : {
measurements : [ ] ImageMeasurementsV2 {
{
Ref : "test-ref" ,
Stream : "nightly" ,
Version : "v1.0.0" ,
List : [ ] ImageMeasurementsV2Entry {
{
CSP : cloudprovider . GCP ,
AttestationVariant : "gcp-sev-es" ,
Measurements : M {
1 : WithAllBytes ( 0x11 , Enforce , PCRMeasurementLength ) ,
} ,
} ,
} ,
} ,
{
Ref : "test-ref" ,
Stream : "nightly" ,
Version : "v1.0.0" ,
List : [ ] ImageMeasurementsV2Entry {
{
CSP : cloudprovider . AWS ,
AttestationVariant : "aws-nitro-tpm" ,
Measurements : M {
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
} ,
} ,
} ,
} ,
} ,
wantMeasurements : ImageMeasurementsV2 {
Ref : "test-ref" ,
Stream : "nightly" ,
Version : "v1.0.0" ,
List : [ ] ImageMeasurementsV2Entry {
{
CSP : cloudprovider . AWS ,
AttestationVariant : "aws-nitro-tpm" ,
Measurements : M {
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
} ,
} ,
{
CSP : cloudprovider . GCP ,
AttestationVariant : "gcp-sev-es" ,
Measurements : M {
1 : WithAllBytes ( 0x11 , Enforce , PCRMeasurementLength ) ,
} ,
} ,
} ,
} ,
} ,
"mismatch in base info" : {
measurements : [ ] ImageMeasurementsV2 {
{
Ref : "test-ref" ,
Stream : "nightly" ,
Version : "v1.0.0" ,
List : [ ] ImageMeasurementsV2Entry {
{
CSP : cloudprovider . AWS ,
AttestationVariant : "aws-nitro-tpm" ,
Measurements : M {
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
} ,
} ,
} ,
} ,
{
Ref : "other-ref" ,
Stream : "stable" ,
Version : "v2.0.0" ,
List : [ ] ImageMeasurementsV2Entry {
{
CSP : cloudprovider . GCP ,
AttestationVariant : "gcp-sev-es" ,
Measurements : M {
1 : WithAllBytes ( 0x11 , Enforce , PCRMeasurementLength ) ,
} ,
} ,
} ,
} ,
} ,
wantErr : true ,
} ,
"empty list" : {
wantErr : true ,
} ,
}
for name , tc := range testCases {
t . Run ( name , func ( t * testing . T ) {
assert := assert . New ( t )
gotMeasurements , err := MergeImageMeasurementsV2 ( tc . measurements ... )
if tc . wantErr {
assert . Error ( err )
return
}
assert . NoError ( err )
assert . Equal ( tc . wantMeasurements , gotMeasurements )
} )
}
}
2023-08-16 04:45:54 -04:00
func TestMeasurementsCompare ( t * testing . T ) {
testCases := map [ string ] struct {
expected M
actual map [ uint32 ] [ ] byte
wantErrs int
wantWarnings int
} {
"no errors" : {
expected : M {
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0x11 , Enforce , PCRMeasurementLength ) ,
} ,
actual : map [ uint32 ] [ ] byte {
0 : bytes . Repeat ( [ ] byte { 0x00 } , PCRMeasurementLength ) ,
1 : bytes . Repeat ( [ ] byte { 0x11 } , PCRMeasurementLength ) ,
} ,
wantErrs : 0 ,
wantWarnings : 0 ,
} ,
"no errors, with warnings" : {
expected : M {
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0x11 , WarnOnly , PCRMeasurementLength ) ,
2 : WithAllBytes ( 0x22 , WarnOnly , PCRMeasurementLength ) ,
} ,
actual : map [ uint32 ] [ ] byte {
0 : bytes . Repeat ( [ ] byte { 0x00 } , PCRMeasurementLength ) ,
1 : bytes . Repeat ( [ ] byte { 0xFF } , PCRMeasurementLength ) ,
2 : bytes . Repeat ( [ ] byte { 0xFF } , PCRMeasurementLength ) ,
} ,
wantErrs : 0 ,
wantWarnings : 2 ,
} ,
"with errors, no warnings" : {
expected : M {
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0x11 , Enforce , PCRMeasurementLength ) ,
2 : WithAllBytes ( 0x22 , Enforce , PCRMeasurementLength ) ,
} ,
actual : map [ uint32 ] [ ] byte {
0 : bytes . Repeat ( [ ] byte { 0x00 } , PCRMeasurementLength ) ,
1 : bytes . Repeat ( [ ] byte { 0xFF } , PCRMeasurementLength ) ,
2 : bytes . Repeat ( [ ] byte { 0xFF } , PCRMeasurementLength ) ,
} ,
wantErrs : 2 ,
wantWarnings : 0 ,
} ,
"with errors and warnings" : {
expected : M {
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0x11 , WarnOnly , PCRMeasurementLength ) ,
2 : WithAllBytes ( 0x22 , Enforce , PCRMeasurementLength ) ,
} ,
actual : map [ uint32 ] [ ] byte {
0 : bytes . Repeat ( [ ] byte { 0x00 } , PCRMeasurementLength ) ,
1 : bytes . Repeat ( [ ] byte { 0xFF } , PCRMeasurementLength ) ,
2 : bytes . Repeat ( [ ] byte { 0xFF } , PCRMeasurementLength ) ,
} ,
wantErrs : 1 ,
wantWarnings : 1 ,
} ,
"extra measurements don't cause errors" : {
expected : M {
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0x11 , Enforce , PCRMeasurementLength ) ,
} ,
actual : map [ uint32 ] [ ] byte {
0 : bytes . Repeat ( [ ] byte { 0x00 } , PCRMeasurementLength ) ,
1 : bytes . Repeat ( [ ] byte { 0x11 } , PCRMeasurementLength ) ,
2 : bytes . Repeat ( [ ] byte { 0x22 } , PCRMeasurementLength ) ,
} ,
wantErrs : 0 ,
wantWarnings : 0 ,
} ,
"missing measurements cause errors" : {
expected : M {
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0x11 , Enforce , PCRMeasurementLength ) ,
2 : WithAllBytes ( 0x22 , Enforce , PCRMeasurementLength ) ,
} ,
actual : map [ uint32 ] [ ] byte {
0 : bytes . Repeat ( [ ] byte { 0x00 } , PCRMeasurementLength ) ,
1 : bytes . Repeat ( [ ] byte { 0x11 } , PCRMeasurementLength ) ,
} ,
wantErrs : 1 ,
wantWarnings : 0 ,
} ,
"missing measurements cause warnings" : {
expected : M {
0 : WithAllBytes ( 0x00 , Enforce , PCRMeasurementLength ) ,
1 : WithAllBytes ( 0x11 , Enforce , PCRMeasurementLength ) ,
2 : WithAllBytes ( 0x22 , WarnOnly , PCRMeasurementLength ) ,
} ,
actual : map [ uint32 ] [ ] byte {
0 : bytes . Repeat ( [ ] byte { 0x00 } , PCRMeasurementLength ) ,
1 : bytes . Repeat ( [ ] byte { 0x11 } , PCRMeasurementLength ) ,
} ,
wantErrs : 0 ,
wantWarnings : 1 ,
} ,
}
for name , tc := range testCases {
t . Run ( name , func ( t * testing . T ) {
assert := assert . New ( t )
gotWarnings , gotErrs := tc . expected . Compare ( tc . actual )
assert . Equal ( tc . wantErrs , len ( gotErrs ) )
assert . Equal ( tc . wantWarnings , len ( gotWarnings ) )
} )
}
}