Add support for system keyring as trust store
This commit is contained in:
parent
d4d06574b8
commit
c0d050e34c
3 changed files with 181 additions and 4 deletions
31
cmd/main.go
31
cmd/main.go
|
@ -32,6 +32,7 @@ var (
|
|||
}
|
||||
|
||||
trustStoreDir string
|
||||
trustStoreKeyring string
|
||||
noSpec string
|
||||
minimumSecurityLevel = 0
|
||||
defaultSymmetricKeySize = 0
|
||||
|
@ -50,7 +51,10 @@ func main() {
|
|||
}
|
||||
|
||||
rootCmd.PersistentFlags().StringVarP(&trustStoreDir, "tsdir", "d", "",
|
||||
"specify a truststore directory (default loaded from JESS_TSDIR env variable)",
|
||||
"specify a truststore directory (default loaded from JESS_TS_DIR env variable)",
|
||||
)
|
||||
rootCmd.PersistentFlags().StringVarP(&trustStoreDir, "tskeyring", "k", "",
|
||||
"specify a truststore keyring namespace (default loaded from JESS_TS_KEYRING env variable) - lower priority than tsdir",
|
||||
)
|
||||
rootCmd.PersistentFlags().StringVarP(&noSpec, "no", "n", "",
|
||||
"remove requirements using the abbreviations C, I, R, S",
|
||||
|
@ -67,17 +71,36 @@ func main() {
|
|||
}
|
||||
|
||||
func initGlobalFlags(cmd *cobra.Command, args []string) (err error) {
|
||||
// trust store
|
||||
// trust store directory
|
||||
if trustStoreDir == "" {
|
||||
trustStoreDir, _ = os.LookupEnv("JESS_TSDIR")
|
||||
trustStoreDir, _ = os.LookupEnv("JESS_TS_DIR")
|
||||
if trustStoreDir == "" {
|
||||
trustStoreDir, _ = os.LookupEnv("JESS_TSDIR")
|
||||
}
|
||||
}
|
||||
if trustStoreDir != "" {
|
||||
var err error
|
||||
trustStore, err = truststores.NewDirTrustStore(trustStoreDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// trust store keyring
|
||||
if trustStore == nil {
|
||||
if trustStoreKeyring == "" {
|
||||
trustStoreKeyring, _ = os.LookupEnv("JESS_TS_KEYRING")
|
||||
if trustStoreKeyring == "" {
|
||||
trustStoreKeyring, _ = os.LookupEnv("JESS_TSKEYRING")
|
||||
}
|
||||
}
|
||||
if trustStoreKeyring != "" {
|
||||
trustStore, err = truststores.NewKeyringTrustStore(trustStoreKeyring)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// requirements
|
||||
if noSpec != "" {
|
||||
requirements, err = jess.ParseRequirementsFromNoSpec(noSpec)
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
package truststores
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/safing/jess"
|
||||
)
|
||||
|
||||
// ErrNotSupportedByTrustStore is returned by trust stores if they do not
|
||||
// support certain actions.
|
||||
var ErrNotSupportedByTrustStore = errors.New("action not supported by trust store")
|
||||
|
||||
// ExtendedTrustStore holds a set of trusted Signets, Recipients and Envelopes.
|
||||
type ExtendedTrustStore interface {
|
||||
jess.TrustStore
|
||||
|
|
148
truststores/keyring.go
Normal file
148
truststores/keyring.go
Normal file
|
@ -0,0 +1,148 @@
|
|||
package truststores
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/zalando/go-keyring"
|
||||
|
||||
"github.com/safing/jess"
|
||||
)
|
||||
|
||||
const (
|
||||
keyringServiceNamePrefix = "jess:"
|
||||
|
||||
keyringSelfcheckKey = "_selfcheck"
|
||||
keyringSelfcheckValue = "!selfcheck"
|
||||
)
|
||||
|
||||
// KeyringTrustStore is a trust store that uses the system keyring.
|
||||
// It does not support listing entries, so it cannot be easily managed.
|
||||
type KeyringTrustStore struct {
|
||||
serviceName string
|
||||
}
|
||||
|
||||
// NewKeyringTrustStore returns a new keyring trust store with the given service name.
|
||||
// The effect of the service name depends on the operating system.
|
||||
// Read more at https://pkg.go.dev/github.com/zalando/go-keyring
|
||||
func NewKeyringTrustStore(serviceName string) (*KeyringTrustStore, error) {
|
||||
krts := &KeyringTrustStore{
|
||||
serviceName: keyringServiceNamePrefix + serviceName,
|
||||
}
|
||||
|
||||
// Run a self-check.
|
||||
err := keyring.Set(krts.serviceName, keyringSelfcheckKey, keyringSelfcheckValue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selfcheckReturn, err := keyring.Get(krts.serviceName, keyringSelfcheckKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if selfcheckReturn != keyringSelfcheckValue {
|
||||
return nil, errors.New("keyring is faulty")
|
||||
}
|
||||
|
||||
return krts, nil
|
||||
}
|
||||
|
||||
// GetSignet returns the Signet with the given ID.
|
||||
func (krts *KeyringTrustStore) GetSignet(id string, recipient bool) (*jess.Signet, error) {
|
||||
// Build ID.
|
||||
if recipient {
|
||||
id += recipientSuffix
|
||||
} else {
|
||||
id += signetSuffix
|
||||
}
|
||||
|
||||
// Get data from keyring.
|
||||
data, err := keyring.Get(krts.serviceName, id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %s", jess.ErrSignetNotFound, err)
|
||||
}
|
||||
|
||||
// Parse and return.
|
||||
return jess.SignetFromBase58(data)
|
||||
}
|
||||
|
||||
// StoreSignet stores a Signet.
|
||||
func (krts *KeyringTrustStore) StoreSignet(signet *jess.Signet) error {
|
||||
// Build ID.
|
||||
var id string
|
||||
if signet.Public {
|
||||
id = signet.ID + recipientSuffix
|
||||
} else {
|
||||
id = signet.ID + signetSuffix
|
||||
}
|
||||
|
||||
// Serialize.
|
||||
data, err := signet.ToBase58()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Save to keyring.
|
||||
return keyring.Set(krts.serviceName, id, data)
|
||||
}
|
||||
|
||||
// DeleteSignet deletes the Signet or Recipient with the given ID.
|
||||
func (krts *KeyringTrustStore) DeleteSignet(id string, recipient bool) error {
|
||||
// Build ID.
|
||||
if recipient {
|
||||
id += recipientSuffix
|
||||
} else {
|
||||
id += signetSuffix
|
||||
}
|
||||
|
||||
// Delete from keyring.
|
||||
return keyring.Delete(krts.serviceName, id)
|
||||
}
|
||||
|
||||
// SelectSignets returns a selection of the signets in the trust store. Results are filtered by tool/algorithm and whether it you're looking for a signet (private key) or a recipient (public key).
|
||||
func (krts *KeyringTrustStore) SelectSignets(filter uint8, schemes ...string) ([]*jess.Signet, error) {
|
||||
return nil, ErrNotSupportedByTrustStore
|
||||
}
|
||||
|
||||
// GetEnvelope returns the Envelope with the given name.
|
||||
func (krts *KeyringTrustStore) GetEnvelope(name string) (*jess.Envelope, error) {
|
||||
// Build ID.
|
||||
name += envelopeSuffix
|
||||
|
||||
// Get data from keyring.
|
||||
data, err := keyring.Get(krts.serviceName, name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %s", jess.ErrEnvelopeNotFound, err)
|
||||
}
|
||||
|
||||
// Parse and return.
|
||||
return jess.EnvelopeFromBase58(data)
|
||||
}
|
||||
|
||||
// StoreEnvelope stores an Envelope.
|
||||
func (krts *KeyringTrustStore) StoreEnvelope(envelope *jess.Envelope) error {
|
||||
// Build ID.
|
||||
name := envelope.Name + envelopeSuffix
|
||||
|
||||
// Serialize.
|
||||
data, err := envelope.ToBase58()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Save to keyring.
|
||||
return keyring.Set(krts.serviceName, name, data)
|
||||
}
|
||||
|
||||
// DeleteEnvelope deletes the Envelope with the given name.
|
||||
func (krts *KeyringTrustStore) DeleteEnvelope(name string) error {
|
||||
// Build ID.
|
||||
name += envelopeSuffix
|
||||
|
||||
// Delete from keyring.
|
||||
return keyring.Delete(krts.serviceName, name)
|
||||
}
|
||||
|
||||
// AllEnvelopes returns all envelopes.
|
||||
func (krts *KeyringTrustStore) AllEnvelopes() ([]*jess.Envelope, error) {
|
||||
return nil, ErrNotSupportedByTrustStore
|
||||
}
|
Loading…
Add table
Reference in a new issue