Update swizzler so that if messing up the root file, we can still get the pub keys and sign.

Signed-off-by: Ying Li <ying.li@docker.com>
This commit is contained in:
Ying Li
2016-01-21 14:05:31 -08:00
parent f8a0e46b6c
commit bb5f9cc170
2 changed files with 73 additions and 36 deletions

View File

@@ -32,21 +32,9 @@ type MetadataSwizzler struct {
Roles []string // list of Roles in the metadataStore
}
// signs the new metadata, replacing whatever signature was there
func serializeMetadata(cs signed.CryptoService, s *data.Signed, role string,
pubKeys ...data.PublicKey) ([]byte, error) {
// delete the existing signatures
s.Signatures = []data.Signature{}
if len(pubKeys) > 0 {
if err := signed.Sign(cs, s, pubKeys...); err != nil {
if _, ok := err.(signed.ErrNoKeys); ok {
return nil, ErrNoKeyForRole{Role: role}
}
return nil, err
}
} else if role == data.CanonicalRootRole {
func getPubKeys(cs signed.CryptoService, s *data.Signed, role string) ([]data.PublicKey, error) {
var pubKeys []data.PublicKey
if role == data.CanonicalRootRole {
// if this is root metadata, we have to get the keys from the root because they
// are certs
root := &data.Root{}
@@ -54,24 +42,37 @@ func serializeMetadata(cs signed.CryptoService, s *data.Signed, role string,
return nil, err
}
for _, pubKeyID := range root.Roles[data.CanonicalRootRole].KeyIDs {
if err := signed.Sign(cs, s, root.Keys[pubKeyID]); err != nil {
if _, ok := err.(signed.ErrNoKeys); ok {
return nil, ErrNoKeyForRole{Role: role}
}
return nil, err
}
pubKeys = append(pubKeys, root.Keys[pubKeyID])
}
} else {
pubKeyIDs := cs.ListKeys(role)
if len(pubKeyIDs) < 1 {
return nil, ErrNoKeyForRole{role}
}
for _, pubKeyID := range pubKeyIDs {
if err := signed.Sign(cs, s, cs.GetKey(pubKeyID)); err != nil {
return nil, err
pubKey := cs.GetKey(pubKeyID)
if pubKey != nil {
pubKeys = append(pubKeys, pubKey)
}
}
}
return pubKeys, nil
}
// signs the new metadata, replacing whatever signature was there
func serializeMetadata(cs signed.CryptoService, s *data.Signed, role string,
pubKeys ...data.PublicKey) ([]byte, error) {
// delete the existing signatures
s.Signatures = []data.Signature{}
if len(pubKeys) < 1 {
return nil, ErrNoKeyForRole{role}
}
if err := signed.Sign(cs, s, pubKeys...); err != nil {
if _, ok := err.(signed.ErrNoKeys); ok {
return nil, ErrNoKeyForRole{Role: role}
}
return nil, err
}
metaBytes, err := json.Marshal(s)
if err != nil {
@@ -160,6 +161,11 @@ func (m *MetadataSwizzler) SetInvalidSignedMeta(role string) error {
return err
}
pubKeys, err := getPubKeys(m.CryptoService, signedThing, role)
if err != nil {
return err
}
var unmarshalled map[string]interface{}
if err := json.Unmarshal(signedThing.Signed, &unmarshalled); err != nil {
return err
@@ -175,7 +181,7 @@ func (m *MetadataSwizzler) SetInvalidSignedMeta(role string) error {
}
signedThing.Signed = json.RawMessage(metaBytes)
metaBytes, err = serializeMetadata(m.CryptoService, signedThing, role)
metaBytes, err = serializeMetadata(m.CryptoService, signedThing, role, pubKeys...)
if err != nil {
return err
}
@@ -206,7 +212,11 @@ func (m *MetadataSwizzler) SetInvalidMetadataType(role string) error {
}
signedThing.Signed = json.RawMessage(metaBytes)
metaBytes, err = serializeMetadata(m.CryptoService, signedThing, role)
pubKeys, err := getPubKeys(m.CryptoService, signedThing, role)
if err == nil {
metaBytes, err = serializeMetadata(m.CryptoService, signedThing, role, pubKeys...)
}
if err != nil {
return err
}
@@ -291,7 +301,11 @@ func (m *MetadataSwizzler) OffsetMetadataVersion(role string, offset int) error
}
signedThing.Signed = json.RawMessage(metaBytes)
metaBytes, err = serializeMetadata(m.CryptoService, signedThing, role)
pubKeys, err := getPubKeys(m.CryptoService, signedThing, role)
if err == nil {
metaBytes, err = serializeMetadata(m.CryptoService, signedThing, role, pubKeys...)
}
if err != nil {
return err
}
@@ -319,7 +333,11 @@ func (m *MetadataSwizzler) ExpireMetadata(role string) error {
}
signedThing.Signed = json.RawMessage(metaBytes)
metaBytes, err = serializeMetadata(m.CryptoService, signedThing, role)
pubKeys, err := getPubKeys(m.CryptoService, signedThing, role)
if err == nil {
metaBytes, err = serializeMetadata(m.CryptoService, signedThing, role, pubKeys...)
}
if err != nil {
return err
}
@@ -370,7 +388,12 @@ func (m *MetadataSwizzler) SetThreshold(role string, newThreshold int) error {
}
}
metaBytes, err := serializeMetadata(m.CryptoService, signedThing, roleSpecifier)
var metaBytes []byte
pubKeys, err := getPubKeys(m.CryptoService, signedThing, roleSpecifier)
if err == nil {
metaBytes, err = serializeMetadata(m.CryptoService, signedThing, roleSpecifier, pubKeys...)
}
if err != nil {
return err
}
@@ -403,7 +426,12 @@ func (m *MetadataSwizzler) ChangeRootKey() error {
return err
}
metaBytes, err := serializeMetadata(m.CryptoService, signedThing, data.CanonicalRootRole)
var metaBytes []byte
pubKeys, err := getPubKeys(m.CryptoService, signedThing, data.CanonicalRootRole)
if err == nil {
metaBytes, err = serializeMetadata(m.CryptoService, signedThing, data.CanonicalRootRole, pubKeys...)
}
if err != nil {
return err
}
@@ -450,7 +478,11 @@ func (m *MetadataSwizzler) UpdateSnapshotHashes(roles ...string) error {
if snapshotSigned, err = snapshot.ToSigned(); err != nil {
return err
}
metaBytes, err = serializeMetadata(m.CryptoService, snapshotSigned, data.CanonicalSnapshotRole)
pubKeys, err := getPubKeys(m.CryptoService, snapshotSigned, data.CanonicalSnapshotRole)
if err == nil {
metaBytes, err = serializeMetadata(m.CryptoService, snapshotSigned, data.CanonicalSnapshotRole, pubKeys...)
}
if err != nil {
return err
}
@@ -490,7 +522,11 @@ func (m *MetadataSwizzler) UpdateTimestampHash() error {
if err != nil {
return err
}
metaBytes, err = serializeMetadata(m.CryptoService, timestampSigned, data.CanonicalTimestampRole)
pubKeys, err := getPubKeys(m.CryptoService, timestampSigned, data.CanonicalTimestampRole)
if err == nil {
metaBytes, err = serializeMetadata(m.CryptoService, timestampSigned, data.CanonicalTimestampRole, pubKeys...)
}
if err != nil {
return err
}

View File

@@ -159,13 +159,13 @@ func TestSwizzlerSetInvalidSigned(t *testing.T) {
func TestSwizzlerSetInvalidSignedMeta(t *testing.T) {
f, origMeta := createNewSwizzler(t)
f.SetInvalidSignedMeta(data.CanonicalTargetsRole)
f.SetInvalidSignedMeta(data.CanonicalRootRole)
for role, metaBytes := range origMeta {
newMeta, err := f.MetadataCache.GetMeta(role, -1)
require.NoError(t, err)
if role != data.CanonicalTargetsRole {
if role != data.CanonicalRootRole {
require.True(t, bytes.Equal(metaBytes, newMeta), "bytes have changed for role %s", role)
} else {
require.False(t, bytes.Equal(metaBytes, newMeta))
@@ -227,6 +227,7 @@ func TestSwizzlerInvalidateMetadataSignatures(t *testing.T) {
require.Equal(t, origSigned.Signatures[i].KeyID, newSigned.Signatures[i].KeyID)
require.Equal(t, origSigned.Signatures[i].Method, newSigned.Signatures[i].Method)
require.NotEqual(t, origSigned.Signatures[i].Signature, newSigned.Signatures[i].Signature)
require.Equal(t, []byte("invalid signature"), newSigned.Signatures[i].Signature)
}
require.True(t, bytes.Equal(origSigned.Signed, newSigned.Signed))
}