2020-02-15 22:13:50 +00:00
|
|
|
package sigcred
|
|
|
|
|
|
|
|
import (
|
2020-03-29 21:16:36 +00:00
|
|
|
"dehub.dev/src/dehub.git/fs"
|
|
|
|
"dehub.dev/src/dehub.git/typeobj"
|
2020-02-15 22:13:50 +00:00
|
|
|
)
|
|
|
|
|
2020-04-26 20:23:03 +00:00
|
|
|
// Signifier describes the methods that all signifiers must implement.
|
|
|
|
type Signifier interface {
|
|
|
|
// Sign returns a credential containing a signature of the given data.
|
|
|
|
//
|
|
|
|
// tree can be used to find the Signifier at a particular snapshot.
|
|
|
|
Sign(fs.FS, []byte) (CredentialUnion, error)
|
|
|
|
|
|
|
|
// Signed returns true if the Signifier was used to sign the credential.
|
|
|
|
Signed(fs.FS, CredentialUnion) (bool, error)
|
|
|
|
|
|
|
|
// Verify asserts that the Signifier produced the given credential for the
|
|
|
|
// given data set, or returns an error.
|
|
|
|
//
|
|
|
|
// tree can be used to find the Signifier at a particular snapshot.
|
|
|
|
Verify(fs.FS, []byte, CredentialUnion) error
|
|
|
|
}
|
|
|
|
|
|
|
|
// SignifierUnion represents a single signifier for an account. Only one field
|
|
|
|
// should be set on each SignifierUnion.
|
|
|
|
type SignifierUnion struct {
|
2020-04-11 23:10:18 +00:00
|
|
|
PGPPublicKey *SignifierPGP `type:"pgp_public_key"`
|
|
|
|
|
2020-04-26 20:23:03 +00:00
|
|
|
// LegacyPGPPublicKeyFile is deprecated, only PGPPublicKey should be used
|
|
|
|
LegacyPGPPublicKeyFile *SignifierPGPFile `type:"pgp_public_key_file"`
|
2020-02-15 22:13:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalYAML implements the yaml.Marshaler interface.
|
2020-04-26 20:23:03 +00:00
|
|
|
func (s SignifierUnion) MarshalYAML() (interface{}, error) {
|
2020-02-15 22:13:50 +00:00
|
|
|
return typeobj.MarshalYAML(s)
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
2020-04-26 20:23:03 +00:00
|
|
|
func (s *SignifierUnion) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
2020-04-11 23:10:18 +00:00
|
|
|
if err := typeobj.UnmarshalYAML(s, unmarshal); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO deprecate PGPPublicKeyFile
|
2020-04-26 20:23:03 +00:00
|
|
|
if s.LegacyPGPPublicKeyFile != nil {
|
|
|
|
s.PGPPublicKey = &SignifierPGP{Path: s.LegacyPGPPublicKeyFile.Path}
|
|
|
|
s.LegacyPGPPublicKeyFile = nil
|
2020-04-11 23:10:18 +00:00
|
|
|
}
|
|
|
|
return nil
|
2020-02-15 22:13:50 +00:00
|
|
|
}
|
|
|
|
|
2020-04-26 20:23:03 +00:00
|
|
|
// Signifier returns the Signifier instance encapsulated by this SignifierUnion.
|
|
|
|
//
|
|
|
|
// This will panic if no Signifier field is populated.
|
2020-03-13 21:24:46 +00:00
|
|
|
//
|
|
|
|
// accountID is given so as to automatically fill the AccountID field of
|
2020-04-26 20:23:03 +00:00
|
|
|
// credentials returned from Sign, since the underlying implementation doesn't
|
2020-03-13 21:24:46 +00:00
|
|
|
// know what account it's signing for.
|
2020-04-26 20:23:03 +00:00
|
|
|
func (s SignifierUnion) Signifier(accountID string) Signifier {
|
2020-02-15 22:13:50 +00:00
|
|
|
el, _, err := typeobj.Element(s)
|
|
|
|
if err != nil {
|
2020-04-26 20:23:03 +00:00
|
|
|
panic(err)
|
2020-02-15 22:13:50 +00:00
|
|
|
}
|
2020-04-26 20:23:03 +00:00
|
|
|
return accountSignifier(accountID, el.(Signifier))
|
2020-02-15 22:13:50 +00:00
|
|
|
}
|
2020-03-13 21:24:46 +00:00
|
|
|
|
2020-04-11 23:10:18 +00:00
|
|
|
type signifierMiddleware struct {
|
2020-04-26 20:23:03 +00:00
|
|
|
Signifier
|
|
|
|
signCallback func(*CredentialUnion)
|
2020-04-11 23:10:18 +00:00
|
|
|
}
|
|
|
|
|
2020-04-26 20:23:03 +00:00
|
|
|
func (sm signifierMiddleware) Sign(fs fs.FS, data []byte) (CredentialUnion, error) {
|
|
|
|
cred, err := sm.Signifier.Sign(fs, data)
|
2020-04-11 23:10:18 +00:00
|
|
|
if err != nil || sm.signCallback == nil {
|
|
|
|
return cred, err
|
|
|
|
}
|
|
|
|
sm.signCallback(&cred)
|
|
|
|
return cred, nil
|
|
|
|
}
|
|
|
|
|
2020-04-26 20:23:03 +00:00
|
|
|
// accountSignifier wraps a Signifier to always set the accountID field on
|
|
|
|
// credentials it produces via the Sign method.
|
2020-03-13 21:24:46 +00:00
|
|
|
//
|
2020-04-26 20:23:03 +00:00
|
|
|
// TODO accountSignifier shouldn't be necessary, it's very ugly. It indicates
|
|
|
|
// that CredentialUnion probably shouldn't have AccountID on it, which makes
|
|
|
|
// sense. Some refactoring is required here.
|
|
|
|
func accountSignifier(accountID string, sig Signifier) Signifier {
|
2020-04-11 23:10:18 +00:00
|
|
|
return signifierMiddleware{
|
2020-04-26 20:23:03 +00:00
|
|
|
Signifier: sig,
|
|
|
|
signCallback: func(cred *CredentialUnion) {
|
2020-04-11 23:10:18 +00:00
|
|
|
cred.AccountID = accountID
|
|
|
|
},
|
|
|
|
}
|
2020-03-13 21:24:46 +00:00
|
|
|
}
|