Commit 35ba6bb1 authored by Sietse Ringers's avatar Sietse Ringers
Browse files

Support scheme auto updating

parent 34fafecc
...@@ -32,6 +32,7 @@ import ( ...@@ -32,6 +32,7 @@ import (
"github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go"
"github.com/go-errors/errors" "github.com/go-errors/errors"
"github.com/jasonlvhit/gocron"
"github.com/privacybydesign/gabi" "github.com/privacybydesign/gabi"
"github.com/privacybydesign/gabi/big" "github.com/privacybydesign/gabi/big"
"github.com/privacybydesign/irmago/internal/fs" "github.com/privacybydesign/irmago/internal/fs"
...@@ -61,6 +62,7 @@ type Configuration struct { ...@@ -61,6 +62,7 @@ type Configuration struct {
initialized bool initialized bool
assets string assets string
readOnly bool readOnly bool
cronchan chan bool
} }
// ConfigurationFileHash encodes the SHA256 hash of an authenticated // ConfigurationFileHash encodes the SHA256 hash of an authenticated
...@@ -1179,6 +1181,41 @@ func (conf *Configuration) UpdateSchemeManager(id SchemeManagerIdentifier, downl ...@@ -1179,6 +1181,41 @@ func (conf *Configuration) UpdateSchemeManager(id SchemeManagerIdentifier, downl
return return
} }
func (conf *Configuration) updateSchemes() error {
for id := range conf.SchemeManagers {
Logger.WithField("scheme", id).Info("Auto-updating scheme")
if err := conf.UpdateSchemeManager(id, nil); err != nil {
return err
}
}
return nil
}
func (conf *Configuration) AutoUpdateSchemes(interval uint) {
Logger.Infof("Updating schemes every %d minutes", interval)
gocron.Every(uint64(interval)).Minutes().Do(func() {
if err := conf.updateSchemes(); err != nil {
Logger.Error("Scheme autoupdater failed: ")
if e, ok := err.(*errors.Error); ok {
Logger.Error(e.ErrorStack())
} else {
Logger.Errorf("%s %s", reflect.TypeOf(err).String(), err.Error())
}
}
})
go gocron.RunAll() // Perform updates now
conf.cronchan = gocron.Start() // Schedule updates (first one in interval minutes from now)
}
func (conf *Configuration) StopAutoUpdateSchemes() {
if conf.cronchan != nil {
Logger.Info("Stopped scheme autoupdater")
conf.cronchan <- true
}
}
// Methods containing consistency checks on irma_configuration // Methods containing consistency checks on irma_configuration
func (conf *Configuration) checkIssuer(manager *SchemeManager, issuer *Issuer, dir string) error { func (conf *Configuration) checkIssuer(manager *SchemeManager, issuer *Issuer, dir string) error {
......
...@@ -29,7 +29,9 @@ type Configuration struct { ...@@ -29,7 +29,9 @@ type Configuration struct {
// Path to writable dir to write cache to (only used if IrmaConfiguration is not given) // Path to writable dir to write cache to (only used if IrmaConfiguration is not given)
CachePath string `json:"cachepath" mapstructure:"cachepath"` CachePath string `json:"cachepath" mapstructure:"cachepath"`
// Whether or not to download default IRMA schemes if the specified irma_configuration is empty // Whether or not to download default IRMA schemes if the specified irma_configuration is empty
DownloadDefaultSchemes bool DownloadDefaultSchemes bool `json:"downloadschemes" mapstructure:"downloadschemes"`
// Update all schemes every x minutes (0 to disable)
SchemeUpdateInterval int `json:"schemeupdate" mapstructure:"schemeupdate"`
// Path to issuer private keys to parse // Path to issuer private keys to parse
IssuerPrivateKeysPath string `json:"privatekeys" mapstructure:"privatekeys"` IssuerPrivateKeysPath string `json:"privatekeys" mapstructure:"privatekeys"`
// Issuer private keys // Issuer private keys
......
...@@ -59,6 +59,12 @@ func Initialize(configuration *server.Configuration) error { ...@@ -59,6 +59,12 @@ func Initialize(configuration *server.Configuration) error {
} }
} }
if conf.SchemeUpdateInterval != 0 {
conf.IrmaConfiguration.AutoUpdateSchemes(uint(conf.SchemeUpdateInterval))
} else {
conf.Logger.Warn("Scheme updating disabled")
}
if conf.IssuerPrivateKeys == nil { if conf.IssuerPrivateKeys == nil {
conf.IssuerPrivateKeys = make(map[irma.IssuerIdentifier]*gabi.PrivateKey) conf.IssuerPrivateKeys = make(map[irma.IssuerIdentifier]*gabi.PrivateKey)
} }
......
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/jasonlvhit/gocron"
"github.com/privacybydesign/gabi" "github.com/privacybydesign/gabi"
"github.com/privacybydesign/gabi/big" "github.com/privacybydesign/gabi/big"
"github.com/privacybydesign/irmago" "github.com/privacybydesign/irmago"
...@@ -58,7 +59,11 @@ var ( ...@@ -58,7 +59,11 @@ var (
func init() { func init() {
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
go sessions.deleteExpired()
gocron.Every(10).Seconds().Do(func() {
sessions.deleteExpired()
})
gocron.Start()
} }
func (s *memorySessionStore) get(token string) *session { func (s *memorySessionStore) get(token string) *session {
...@@ -78,6 +83,8 @@ func (s *memorySessionStore) update(token string, session *session) { ...@@ -78,6 +83,8 @@ func (s *memorySessionStore) update(token string, session *session) {
} }
func (s memorySessionStore) deleteExpired() { func (s memorySessionStore) deleteExpired() {
conf.Logger.Trace("Deleting expired sessions")
// First check which sessions have expired // First check which sessions have expired
// We don't need a write lock for this yet, so postpone that for actual deleting // We don't need a write lock for this yet, so postpone that for actual deleting
s.RLock() s.RLock()
...@@ -110,11 +117,6 @@ func (s memorySessionStore) deleteExpired() { ...@@ -110,11 +117,6 @@ func (s memorySessionStore) deleteExpired() {
delete(s.m, token) delete(s.m, token)
} }
s.Unlock() s.Unlock()
// Schedule next run
time.AfterFunc(expiryTicker, func() {
s.deleteExpired()
})
} }
var one *big.Int = big.NewInt(1) var one *big.Int = big.NewInt(1)
......
...@@ -73,6 +73,7 @@ func setFlags(cmd *cobra.Command) error { ...@@ -73,6 +73,7 @@ func setFlags(cmd *cobra.Command) error {
flags.StringP("irmaconf", "i", "", "path to irma_configuration") flags.StringP("irmaconf", "i", "", "path to irma_configuration")
flags.StringP("privatekeys", "k", "", "path to IRMA private keys") flags.StringP("privatekeys", "k", "", "path to IRMA private keys")
flags.String("cachepath", cachepath, "Directory for writing cache files to") flags.String("cachepath", cachepath, "Directory for writing cache files to")
flags.Uint("schemeupdate", 60, "Update IRMA schemes every x minutes (0 to disable)")
flags.StringP("jwtissuer", "j", "irmaserver", "JWT issuer") flags.StringP("jwtissuer", "j", "irmaserver", "JWT issuer")
flags.StringP("jwtprivatekey", "w", "", "JWT private key or path to it") flags.StringP("jwtprivatekey", "w", "", "JWT private key or path to it")
flags.Int("maxrequestage", 300, "Max age in seconds of a session request JWT") flags.Int("maxrequestage", 300, "Max age in seconds of a session request JWT")
...@@ -138,6 +139,7 @@ func configure() error { ...@@ -138,6 +139,7 @@ func configure() error {
IssuerPrivateKeysPath: viper.GetString("privatekeys"), IssuerPrivateKeysPath: viper.GetString("privatekeys"),
CachePath: viper.GetString("cachepath"), CachePath: viper.GetString("cachepath"),
URL: viper.GetString("url"), URL: viper.GetString("url"),
SchemeUpdateInterval: viper.GetInt("schemeupdate"),
Logger: logger, Logger: logger,
}, },
ListenAddress: viper.GetString("listenaddr"), ListenAddress: viper.GetString("listenaddr"),
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment