AB#2159 Feat/cli/fetch measurements (#301)

Signed-off-by: Fabian Kammel <fk@edgeless.systems>
This commit is contained in:
Fabian Kammel 2022-08-01 09:37:05 +02:00 committed by GitHub
parent 7baf98f014
commit 050e8fdc4a
16 changed files with 1430 additions and 496 deletions

View file

@ -1,9 +1,17 @@
package config
import (
"bytes"
"context"
"encoding/base64"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"github.com/edgelesssys/constellation/internal/attestation/vtpm"
"github.com/edgelesssys/constellation/internal/sigstore"
"gopkg.in/yaml.v2"
)
type Measurements map[uint32][]byte
@ -30,6 +38,36 @@ var (
}
)
// FetchAndVerify fetches measurement and signature files via provided URLs,
// using client for download. The publicKey is used to verify the measurements.
func (m *Measurements) FetchAndVerify(ctx context.Context, client *http.Client, measurementsURL *url.URL, signatureURL *url.URL, publicKey []byte) error {
measurements, err := getFromURL(ctx, client, measurementsURL)
if err != nil {
return err
}
signature, err := getFromURL(ctx, client, signatureURL)
if err != nil {
return err
}
if err := sigstore.VerifySignature(measurements, signature, publicKey); err != nil {
return err
}
if err := yaml.NewDecoder(bytes.NewReader(measurements)).Decode(&m); err != nil {
return err
}
return nil
}
// CopyFrom copies over all values from other. Overwriting existing values,
// but keeping not specified values untouched.
func (m Measurements) CopyFrom(other Measurements) {
for idx := range other {
m[idx] = other[idx]
}
}
// MarshalYAML overwrites the default behaviour of writing out []byte not as
// single bytes, but as a single base64 encoded string.
func (m Measurements) MarshalYAML() (interface{}, error) {
base64Map := make(map[uint32]string)
@ -40,6 +78,8 @@ func (m Measurements) MarshalYAML() (interface{}, error) {
return base64Map, nil
}
// UnmarshalYAML overwrites the default behaviour of reading []byte not as
// single bytes, but as a single base64 encoded string.
func (m *Measurements) UnmarshalYAML(unmarshal func(interface{}) error) error {
base64Map := make(map[uint32]string)
err := unmarshal(base64Map)
@ -57,3 +97,24 @@ func (m *Measurements) UnmarshalYAML(unmarshal func(interface{}) error) error {
}
return nil
}
func getFromURL(ctx context.Context, client *http.Client, sourceURL *url.URL) ([]byte, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, sourceURL.String(), http.NoBody)
if err != nil {
return []byte{}, err
}
resp, err := client.Do(req)
if err != nil {
return []byte{}, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return []byte{}, fmt.Errorf("http status code: %d", resp.StatusCode)
}
content, err := ioutil.ReadAll(resp.Body)
if err != nil {
return []byte{}, err
}
return content, nil
}