Rename the validation functions and add more tests

Signed-off-by: Ying Li <ying.li@docker.com>
This commit is contained in:
Ying Li 2016-02-16 11:32:15 -08:00
parent 314cfb9a17
commit 57e28e4f09
8 changed files with 87 additions and 20 deletions

View File

@ -24,10 +24,10 @@ type Root struct {
ConsistentSnapshot bool `json:"consistent_snapshot"` ConsistentSnapshot bool `json:"consistent_snapshot"`
} }
// isValidRoot returns an error, or nil, depending on whether the content of the struct // isValidRootStructure returns an error, or nil, depending on whether the content of the struct
// is valid for root metadata. This does not check signatures or expiry, just that // is valid for root metadata. This does not check signatures or expiry, just that
// the metadata content is valid. // the metadata content is valid.
func isValidRoot(r Root) error { func isValidRootStructure(r Root) error {
expectedType := TUFTypes[CanonicalRootRole] expectedType := TUFTypes[CanonicalRootRole]
if r.Type != expectedType { if r.Type != expectedType {
return ErrInvalidMeta{ return ErrInvalidMeta{
@ -114,10 +114,10 @@ func (r *SignedRoot) MarshalJSON() ([]byte, error) {
// that it is a valid SignedRoot // that it is a valid SignedRoot
func RootFromSigned(s *Signed) (*SignedRoot, error) { func RootFromSigned(s *Signed) (*SignedRoot, error) {
r := Root{} r := Root{}
if err := json.Unmarshal(s.Signed, &r); err != nil { if err := defaultSerializer.Unmarshal(s.Signed, &r); err != nil {
return nil, err return nil, err
} }
if err := isValidRoot(r); err != nil { if err := isValidRootStructure(r); err != nil {
return nil, err return nil, err
} }
sigs := make([]Signature, len(s.Signatures)) sigs := make([]Signature, len(s.Signatures))

View File

@ -16,10 +16,14 @@ type errorSerializer struct {
canonicalJSON canonicalJSON
} }
func (e errorSerializer) MarshalCanonical(from interface{}) ([]byte, error) { func (e errorSerializer) MarshalCanonical(interface{}) ([]byte, error) {
return nil, fmt.Errorf("bad") return nil, fmt.Errorf("bad")
} }
func (e errorSerializer) Unmarshal([]byte, interface{}) error {
return fmt.Errorf("bad")
}
func validRootTemplate() *SignedRoot { func validRootTemplate() *SignedRoot {
return &SignedRoot{ return &SignedRoot{
Signed: Root{ Signed: Root{
@ -124,6 +128,17 @@ func TestRootMarshalJSONMarshallingErrorsPropagated(t *testing.T) {
require.EqualError(t, err, "bad") require.EqualError(t, err, "bad")
} }
func TestRootFromSignedUnmarshallingErrorsPropagated(t *testing.T) {
signed, err := validRootTemplate().ToSigned()
require.NoError(t, err)
setDefaultSerializer(errorSerializer{})
defer setDefaultSerializer(canonicalJSON{})
_, err = RootFromSigned(signed)
require.EqualError(t, err, "bad")
}
// RootFromSigned succeeds if the root is valid, and copies the signatures // RootFromSigned succeeds if the root is valid, and copies the signatures
// rather than assigns them // rather than assigns them
func TestRootFromSignedCopiesSignatures(t *testing.T) { func TestRootFromSignedCopiesSignatures(t *testing.T) {

View File

@ -24,10 +24,10 @@ type Snapshot struct {
Meta Files `json:"meta"` Meta Files `json:"meta"`
} }
// isValidSnapshot returns an error, or nil, depending on whether the content of the struct // isValidSnapshotStructure returns an error, or nil, depending on whether the content of the
// is valid for snapshot metadata. This does not check signatures or expiry, just that // struct is valid for snapshot metadata. This does not check signatures or expiry, just that
// the metadata content is valid. // the metadata content is valid.
func isValidSnapshot(s Snapshot) error { func isValidSnapshotStructure(s Snapshot) error {
expectedType := TUFTypes[CanonicalSnapshotRole] expectedType := TUFTypes[CanonicalSnapshotRole]
if s.Type != expectedType { if s.Type != expectedType {
return ErrInvalidMeta{ return ErrInvalidMeta{
@ -140,10 +140,10 @@ func (sp *SignedSnapshot) MarshalJSON() ([]byte, error) {
// SnapshotFromSigned fully unpacks a Signed object into a SignedSnapshot // SnapshotFromSigned fully unpacks a Signed object into a SignedSnapshot
func SnapshotFromSigned(s *Signed) (*SignedSnapshot, error) { func SnapshotFromSigned(s *Signed) (*SignedSnapshot, error) {
sp := Snapshot{} sp := Snapshot{}
if err := json.Unmarshal(s.Signed, &sp); err != nil { if err := defaultSerializer.Unmarshal(s.Signed, &sp); err != nil {
return nil, err return nil, err
} }
if err := isValidSnapshot(sp); err != nil { if err := isValidSnapshotStructure(sp); err != nil {
return nil, err return nil, err
} }
sigs := make([]Signature, len(s.Signatures)) sigs := make([]Signature, len(s.Signatures))

View File

@ -17,6 +17,7 @@ func validSnapshotTemplate() *SignedSnapshot {
Type: "Snapshot", Version: 1, Expires: time.Now(), Meta: Files{ Type: "Snapshot", Version: 1, Expires: time.Now(), Meta: Files{
CanonicalRootRole: FileMeta{}, CanonicalRootRole: FileMeta{},
CanonicalTargetsRole: FileMeta{}, CanonicalTargetsRole: FileMeta{},
"targets/a": FileMeta{},
}}, }},
Signatures: []Signature{ Signatures: []Signature{
{KeyID: "key1", Method: "method1", Signature: []byte("hello")}, {KeyID: "key1", Method: "method1", Signature: []byte("hello")},
@ -101,6 +102,17 @@ func TestSnapshotMarshalJSONMarshallingErrorsPropagated(t *testing.T) {
require.EqualError(t, err, "bad") require.EqualError(t, err, "bad")
} }
func TestSnapshotFromSignedUnmarshallingErrorsPropagated(t *testing.T) {
signed, err := validSnapshotTemplate().ToSigned()
require.NoError(t, err)
setDefaultSerializer(errorSerializer{})
defer setDefaultSerializer(canonicalJSON{})
_, err = SnapshotFromSigned(signed)
require.EqualError(t, err, "bad")
}
// SnapshotFromSigned succeeds if the snapshot is valid, and copies the signatures // SnapshotFromSigned succeeds if the snapshot is valid, and copies the signatures
// rather than assigns them // rather than assigns them
func TestSnapshotFromSignedCopiesSignatures(t *testing.T) { func TestSnapshotFromSignedCopiesSignatures(t *testing.T) {
@ -168,7 +180,7 @@ func TestSnapshotGetMeta(t *testing.T) {
require.IsType(t, &FileMeta{}, f) require.IsType(t, &FileMeta{}, f)
// now one that doesn't exist // now one that doesn't exist
f, err = ts.GetMeta("targets/a") f, err = ts.GetMeta("targets/a/b")
require.Error(t, err) require.Error(t, err)
require.IsType(t, ErrMissingMeta{}, err) require.IsType(t, ErrMissingMeta{}, err)
require.Nil(t, f) require.Nil(t, f)

View File

@ -23,10 +23,14 @@ type Targets struct {
Delegations Delegations `json:"delegations,omitempty"` Delegations Delegations `json:"delegations,omitempty"`
} }
// isValidTargets returns an error, or nil, depending on whether the content of the struct // isValidTargetsStructure returns an error, or nil, depending on whether the content of the struct
// is valid for targets metadata. This does not check signatures or expiry, just that // is valid for targets metadata. This does not check signatures or expiry, just that
// the metadata content is valid. // the metadata content is valid.
func isValidTargets(t Targets, roleName string) error { func isValidTargetsStructure(t Targets, roleName string) error {
if roleName != CanonicalTargetsRole && !IsDelegation(roleName) {
return ErrInvalidRole{Role: roleName}
}
// even if it's a delegated role, the metadata type is "Targets" // even if it's a delegated role, the metadata type is "Targets"
expectedType := TUFTypes[CanonicalTargetsRole] expectedType := TUFTypes[CanonicalTargetsRole]
if t.Type != expectedType { if t.Type != expectedType {
@ -145,10 +149,10 @@ func (t *SignedTargets) MarshalJSON() ([]byte, error) {
// a role name (so it can validate the SignedTargets object) // a role name (so it can validate the SignedTargets object)
func TargetsFromSigned(s *Signed, roleName string) (*SignedTargets, error) { func TargetsFromSigned(s *Signed, roleName string) (*SignedTargets, error) {
t := Targets{} t := Targets{}
if err := json.Unmarshal(s.Signed, &t); err != nil { if err := defaultSerializer.Unmarshal(s.Signed, &t); err != nil {
return nil, err return nil, err
} }
if err := isValidTargets(t, roleName); err != nil { if err := isValidTargetsStructure(t, roleName); err != nil {
return nil, err return nil, err
} }
sigs := make([]Signature, len(s.Signatures)) sigs := make([]Signature, len(s.Signatures))

View File

@ -108,6 +108,17 @@ func TestTargetsMarshalJSONMarshallingErrorsPropagated(t *testing.T) {
require.EqualError(t, err, "bad") require.EqualError(t, err, "bad")
} }
func TestTargetsFromSignedUnmarshallingErrorsPropagated(t *testing.T) {
signed, err := validTargetsTemplate().ToSigned()
require.NoError(t, err)
setDefaultSerializer(errorSerializer{})
defer setDefaultSerializer(canonicalJSON{})
_, err = TargetsFromSigned(signed, CanonicalTargetsRole)
require.EqualError(t, err, "bad")
}
// TargetsFromSigned succeeds if the targets is valid, and copies the signatures // TargetsFromSigned succeeds if the targets is valid, and copies the signatures
// rather than assigns them // rather than assigns them
func TestTargetsFromSignedCopiesSignatures(t *testing.T) { func TestTargetsFromSignedCopiesSignatures(t *testing.T) {
@ -127,7 +138,7 @@ func TestTargetsFromSignedCopiesSignatures(t *testing.T) {
// If the targets metadata contains delegations which are invalid, the targets metadata // If the targets metadata contains delegations which are invalid, the targets metadata
// fails to validate and thus fails to convert into a SignedTargets // fails to validate and thus fails to convert into a SignedTargets
func TestTargetsBaseFromSignedValidatesDelegations(t *testing.T) { func TestTargetsFromSignedValidatesDelegations(t *testing.T) {
for _, roleName := range []string{CanonicalTargetsRole, path.Join(CanonicalTargetsRole, "a")} { for _, roleName := range []string{CanonicalTargetsRole, path.Join(CanonicalTargetsRole, "a")} {
targets := validTargetsTemplate() targets := validTargetsTemplate()
delgRole, err := NewRole(path.Join(roleName, "b"), 1, []string{"key1"}, nil, nil) delgRole, err := NewRole(path.Join(roleName, "b"), 1, []string{"key1"}, nil, nil)
@ -142,6 +153,8 @@ func TestTargetsBaseFromSignedValidatesDelegations(t *testing.T) {
require.Error(t, err) require.Error(t, err)
require.IsType(t, ErrInvalidMeta{}, err) require.IsType(t, ErrInvalidMeta{}, err)
delgRole.Threshold = 1
// Keys that aren't in the list of keys // Keys that aren't in the list of keys
delgRole.KeyIDs = []string{"keys11"} delgRole.KeyIDs = []string{"keys11"}
s, err = targets.ToSigned() s, err = targets.ToSigned()
@ -202,3 +215,15 @@ func TestTargetsFromSignedValidatesRoleType(t *testing.T) {
require.Equal(t, "Targets", sTargets.Signed.Type) require.Equal(t, "Targets", sTargets.Signed.Type)
} }
} }
// The rolename passed to TargetsFromSigned must be a valid targets role name
func TestTargetsFromSignedValidatesRoleName(t *testing.T) {
for _, roleName := range []string{"TARGETS", "root/a"} {
tg := validTargetsTemplate()
s, err := tg.ToSigned()
require.NoError(t, err)
_, err = TargetsFromSigned(s, roleName)
require.IsType(t, ErrInvalidRole{}, err)
}
}

View File

@ -23,10 +23,10 @@ type Timestamp struct {
Meta Files `json:"meta"` Meta Files `json:"meta"`
} }
// isValidTimestamp returns an error, or nil, depending on whether the content of the struct // isValidTimestampStructure returns an error, or nil, depending on whether the content of the struct
// is valid for timestamp metadata. This does not check signatures or expiry, just that // is valid for timestamp metadata. This does not check signatures or expiry, just that
// the metadata content is valid. // the metadata content is valid.
func isValidTimestamp(t Timestamp) error { func isValidTimestampStructure(t Timestamp) error {
expectedType := TUFTypes[CanonicalTimestampRole] expectedType := TUFTypes[CanonicalTimestampRole]
if t.Type != expectedType { if t.Type != expectedType {
return ErrInvalidMeta{ return ErrInvalidMeta{
@ -105,10 +105,10 @@ func (ts *SignedTimestamp) MarshalJSON() ([]byte, error) {
// SignedTimestamp // SignedTimestamp
func TimestampFromSigned(s *Signed) (*SignedTimestamp, error) { func TimestampFromSigned(s *Signed) (*SignedTimestamp, error) {
ts := Timestamp{} ts := Timestamp{}
if err := json.Unmarshal(s.Signed, &ts); err != nil { if err := defaultSerializer.Unmarshal(s.Signed, &ts); err != nil {
return nil, err return nil, err
} }
if err := isValidTimestamp(ts); err != nil { if err := isValidTimestampStructure(ts); err != nil {
return nil, err return nil, err
} }
sigs := make([]Signature, len(s.Signatures)) sigs := make([]Signature, len(s.Signatures))

View File

@ -100,6 +100,17 @@ func TestTimestampMarshalJSONMarshallingErrorsPropagated(t *testing.T) {
require.EqualError(t, err, "bad") require.EqualError(t, err, "bad")
} }
func TestTimestampFromSignedUnmarshallingErrorsPropagated(t *testing.T) {
signed, err := validTimestampTemplate().ToSigned()
require.NoError(t, err)
setDefaultSerializer(errorSerializer{})
defer setDefaultSerializer(canonicalJSON{})
_, err = TimestampFromSigned(signed)
require.EqualError(t, err, "bad")
}
// TimestampFromSigned succeeds if the timestamp is valid, and copies the signatures // TimestampFromSigned succeeds if the timestamp is valid, and copies the signatures
// rather than assigns them // rather than assigns them
func TestTimestampFromSignedCopiesSignatures(t *testing.T) { func TestTimestampFromSignedCopiesSignatures(t *testing.T) {