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
|
trustStoreDir string
|
||||||
|
trustStoreKeyring string
|
||||||
noSpec string
|
noSpec string
|
||||||
minimumSecurityLevel = 0
|
minimumSecurityLevel = 0
|
||||||
defaultSymmetricKeySize = 0
|
defaultSymmetricKeySize = 0
|
||||||
|
@ -50,7 +51,10 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
rootCmd.PersistentFlags().StringVarP(&trustStoreDir, "tsdir", "d", "",
|
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", "",
|
rootCmd.PersistentFlags().StringVarP(&noSpec, "no", "n", "",
|
||||||
"remove requirements using the abbreviations C, I, R, S",
|
"remove requirements using the abbreviations C, I, R, S",
|
||||||
|
@ -67,17 +71,36 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func initGlobalFlags(cmd *cobra.Command, args []string) (err error) {
|
func initGlobalFlags(cmd *cobra.Command, args []string) (err error) {
|
||||||
// trust store
|
// trust store directory
|
||||||
if trustStoreDir == "" {
|
if trustStoreDir == "" {
|
||||||
trustStoreDir, _ = os.LookupEnv("JESS_TSDIR")
|
trustStoreDir, _ = os.LookupEnv("JESS_TS_DIR")
|
||||||
|
if trustStoreDir == "" {
|
||||||
|
trustStoreDir, _ = os.LookupEnv("JESS_TSDIR")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if trustStoreDir != "" {
|
if trustStoreDir != "" {
|
||||||
var err error
|
|
||||||
trustStore, err = truststores.NewDirTrustStore(trustStoreDir)
|
trustStore, err = truststores.NewDirTrustStore(trustStoreDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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
|
// requirements
|
||||||
if noSpec != "" {
|
if noSpec != "" {
|
||||||
requirements, err = jess.ParseRequirementsFromNoSpec(noSpec)
|
requirements, err = jess.ParseRequirementsFromNoSpec(noSpec)
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
package truststores
|
package truststores
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
"github.com/safing/jess"
|
"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.
|
// ExtendedTrustStore holds a set of trusted Signets, Recipients and Envelopes.
|
||||||
type ExtendedTrustStore interface {
|
type ExtendedTrustStore interface {
|
||||||
jess.TrustStore
|
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