blob: cb49b8930e017f8b66f3f6a9b27cdf1440e438a7 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package repo
import (
"encoding/json"
"fmt"
tuf_data "github.com/flynn/go-tuf/data"
)
// Config is a struct that mirrors an associated FIDL table
// definition in //sdk/fidl/fuchsia.pkg/repo.fidl. Documentation is as in
// that file. Ditto for the types that comprise its definition.
//
// Keep these in sync with their repo.fidl counterparts as well as the custom
//
type Config struct {
URL string `json:"repo_url"`
RootKeys []KeyConfig `json:"root_keys"`
Mirrors []MirrorConfig `json:"mirrors"`
RootVersion uint32 `json:"root_version"`
RootThreshold uint32 `json:"root_threshold"`
UpdatePackageURL string `json:"update_package_url,omitempty"`
}
type MirrorConfig struct {
URL string `json:"mirror_url"`
Subscribe bool `json:"subscribe"`
BlobURL string `json:"blob_mirror_url,omitempty"`
}
type KeyConfig struct {
// ED25519Key is a 32-byte, lowercase, hex-encoded key.
ED25519Key string
}
// We replicate the serialization/deserialization logic given in
// //src/sys/pkg/lib/fidl-fuchsia-pkg-ext/src/repo.rs;
// Per this logic, we set the BlobURL field in MirrorConfig as omitempty (above),
// and give custom marshaling logic to the key config.
//
// This alias allows to make use of the default (un)marshalling logic of Config as we redefine it.
type config Config
func (cfg *Config) MarshalJSON() ([]byte, error) {
cfg2 := config(*cfg)
if cfg2.RootVersion == 0 {
cfg2.RootVersion = 1
}
if cfg2.RootThreshold == 0 {
cfg2.RootThreshold = 1
}
return json.Marshal(&cfg2)
}
func (cfg *Config) UnmarshalJSON(data []byte) error {
var cfg2 config
if err := json.Unmarshal(data, &cfg2); err != nil {
return err
}
if cfg2.RootVersion == 0 {
cfg2.RootVersion = 1
}
if cfg2.RootThreshold == 0 {
cfg2.RootThreshold = 1
}
*cfg = Config(cfg2)
return nil
}
type typeAndValue struct {
Type string `json:"type"`
Value string `json:"value"`
}
func (key *KeyConfig) MarshalJSON() ([]byte, error) {
return json.Marshal(&typeAndValue{
Type: tuf_data.KeyTypeEd25519,
Value: key.ED25519Key,
})
}
func (key *KeyConfig) UnmarshalJSON(data []byte) error {
var tv typeAndValue
if err := json.Unmarshal(data, &tv); err != nil {
return err
}
switch tv.Type {
case tuf_data.KeyTypeEd25519:
key.ED25519Key = tv.Value
return nil
default:
return fmt.Errorf("unexpected key type: %q", tv.Type)
}
}
// GetRootKeys returns the list of public key config objects as read from the
// contents of a repository's root metadata file.
func GetRootKeys(root *tuf_data.Root) ([]KeyConfig, error) {
var rootKeys []KeyConfig
for _, k := range root.UniqueKeys()["root"] {
v := k.Value.Public.String()
var key KeyConfig
switch k.Type {
case tuf_data.KeyTypeEd25519:
key.ED25519Key = v
default:
return nil, fmt.Errorf("unexpected key type: %q", k.Type)
}
rootKeys = append(rootKeys, key)
}
return rootKeys, nil
}