thoth/changeset/changeset.go

55 lines
1.1 KiB
Go

package changeset
import (
"fmt"
"golang.org/x/crypto/ssh"
)
// Metadata is the metadata for the changeset.
type Metadata struct {
// The name of the service
Name string
// The git hash of the repo checkout that made the service
Version string
// Slug SHA256 hash, this is what is signed
Hash []byte
// The SSH signatures for this ChangeSet
Signatures []*ssh.Signature
}
type ChangeSet struct {
Metadata Metadata
SlugFile string
}
func (cs ChangeSet) Validate(trustedKeys []ssh.PublicKey, minNeeded int) error {
var gotKeys = map[string]struct{}{}
for _, sig := range cs.Metadata.Signatures {
for _, pubkey := range trustedKeys {
fp := ssh.FingerprintSHA256(pubkey)
if _, got := gotKeys[fp]; got {
return fmt.Errorf("changeset: %v signed this changeset more than once", fp)
}
if fp != string(sig.Rest) {
continue
}
err := pubkey.Verify(cs.Metadata.Hash, sig)
if err != nil {
return err
}
gotKeys[fp] = struct{}{}
}
}
if gk := len(gotKeys); gk != minNeeded {
return fmt.Errorf("wanted %d keys, only signed with %d keys", minNeeded, gk)
}
return nil
}