mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-12-15 10:54:29 -05:00
c9cae643e2
* Fix unmarshalling attestation version numbers from JSON * Add unit test for UnmarshalJSON --------- Signed-off-by: Daniel Weiße <dw@edgeless.systems>
96 lines
2.6 KiB
Go
96 lines
2.6 KiB
Go
/*
|
|
Copyright (c) Edgeless Systems GmbH
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only
|
|
*/
|
|
|
|
package config
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"math"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
const placeholderVersionValue = 0
|
|
|
|
// NewLatestPlaceholderVersion returns the latest version with a placeholder version value.
|
|
func NewLatestPlaceholderVersion() AttestationVersion {
|
|
return AttestationVersion{
|
|
Value: placeholderVersionValue,
|
|
WantLatest: true,
|
|
}
|
|
}
|
|
|
|
// AttestationVersion is a type that represents a version of a SNP.
|
|
type AttestationVersion struct {
|
|
Value uint8
|
|
WantLatest bool
|
|
}
|
|
|
|
// MarshalYAML implements a custom marshaller to resolve "latest" values.
|
|
func (v AttestationVersion) MarshalYAML() (any, error) {
|
|
if v.WantLatest {
|
|
return "latest", nil
|
|
}
|
|
return v.Value, nil
|
|
}
|
|
|
|
// UnmarshalYAML implements a custom unmarshaller to resolve "atest" values.
|
|
func (v *AttestationVersion) UnmarshalYAML(unmarshal func(any) error) error {
|
|
var rawUnmarshal string
|
|
if err := unmarshal(&rawUnmarshal); err != nil {
|
|
return fmt.Errorf("raw unmarshal: %w", err)
|
|
}
|
|
|
|
return v.parseRawUnmarshal(rawUnmarshal)
|
|
}
|
|
|
|
// MarshalJSON implements a custom marshaller to resolve "latest" values.
|
|
func (v AttestationVersion) MarshalJSON() ([]byte, error) {
|
|
if v.WantLatest {
|
|
return json.Marshal("latest")
|
|
}
|
|
return json.Marshal(v.Value)
|
|
}
|
|
|
|
// UnmarshalJSON implements a custom unmarshaller to resolve "latest" values.
|
|
func (v *AttestationVersion) UnmarshalJSON(data []byte) (err error) {
|
|
// JSON has two distinct ways to represent numbers and strings.
|
|
// This means we cannot simply unmarshal to string, like with YAML.
|
|
// Unmarshalling to `any` causes Go to unmarshal numbers to float64.
|
|
// Therefore, try to unmarshal to string, and then to int, instead of using type assertions.
|
|
var unmarshalString string
|
|
if err := json.Unmarshal(data, &unmarshalString); err != nil {
|
|
var unmarshalInt int64
|
|
if err := json.Unmarshal(data, &unmarshalInt); err != nil {
|
|
return fmt.Errorf("unable to unmarshal to string or int: %w", err)
|
|
}
|
|
unmarshalString = strconv.FormatInt(unmarshalInt, 10)
|
|
}
|
|
|
|
return v.parseRawUnmarshal(unmarshalString)
|
|
}
|
|
|
|
func (v *AttestationVersion) parseRawUnmarshal(str string) error {
|
|
if strings.HasPrefix(str, "0") && len(str) != 1 {
|
|
return fmt.Errorf("no format with prefixed 0 (octal, hexadecimal) allowed: %s", str)
|
|
}
|
|
if strings.ToLower(str) == "latest" {
|
|
v.WantLatest = true
|
|
v.Value = placeholderVersionValue
|
|
} else {
|
|
ui, err := strconv.ParseUint(str, 10, 8)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid version value: %s", str)
|
|
}
|
|
if ui > math.MaxUint8 {
|
|
return fmt.Errorf("integer value is out ouf uint8 range: %d", ui)
|
|
}
|
|
v.Value = uint8(ui)
|
|
}
|
|
return nil
|
|
}
|