|
|
|
|
@ -40,14 +40,17 @@ var ( |
|
|
|
|
pluginScanningErrors map[string]*PluginError |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
type unsignedPluginConditionFunc = func(plugin *PluginBase) bool |
|
|
|
|
|
|
|
|
|
type PluginScanner struct { |
|
|
|
|
pluginPath string |
|
|
|
|
errors []error |
|
|
|
|
backendPluginManager backendplugin.Manager |
|
|
|
|
cfg *setting.Cfg |
|
|
|
|
requireSigned bool |
|
|
|
|
log log.Logger |
|
|
|
|
plugins map[string]*PluginBase |
|
|
|
|
pluginPath string |
|
|
|
|
errors []error |
|
|
|
|
backendPluginManager backendplugin.Manager |
|
|
|
|
cfg *setting.Cfg |
|
|
|
|
requireSigned bool |
|
|
|
|
log log.Logger |
|
|
|
|
plugins map[string]*PluginBase |
|
|
|
|
allowUnsignedPluginsCondition unsignedPluginConditionFunc |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type PluginManager struct { |
|
|
|
|
@ -55,6 +58,10 @@ type PluginManager struct { |
|
|
|
|
Cfg *setting.Cfg `inject:""` |
|
|
|
|
log log.Logger |
|
|
|
|
scanningErrors []error |
|
|
|
|
|
|
|
|
|
// AllowUnsignedPluginsCondition changes the policy for allowing unsigned plugins. Signature validation only runs when plugins are starting
|
|
|
|
|
// and running plugins will not be terminated if they violate the new policy.
|
|
|
|
|
AllowUnsignedPluginsCondition unsignedPluginConditionFunc |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func init() { |
|
|
|
|
@ -187,12 +194,13 @@ func (pm *PluginManager) scanPluginPaths() error { |
|
|
|
|
// scan a directory for plugins.
|
|
|
|
|
func (pm *PluginManager) scan(pluginDir string, requireSigned bool) error { |
|
|
|
|
scanner := &PluginScanner{ |
|
|
|
|
pluginPath: pluginDir, |
|
|
|
|
backendPluginManager: pm.BackendPluginManager, |
|
|
|
|
cfg: pm.Cfg, |
|
|
|
|
requireSigned: requireSigned, |
|
|
|
|
log: pm.log, |
|
|
|
|
plugins: map[string]*PluginBase{}, |
|
|
|
|
pluginPath: pluginDir, |
|
|
|
|
backendPluginManager: pm.BackendPluginManager, |
|
|
|
|
cfg: pm.Cfg, |
|
|
|
|
requireSigned: requireSigned, |
|
|
|
|
log: pm.log, |
|
|
|
|
plugins: map[string]*PluginBase{}, |
|
|
|
|
allowUnsignedPluginsCondition: pm.AllowUnsignedPluginsCondition, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 1st pass: Scan plugins, also mapping plugins to their respective directories
|
|
|
|
|
@ -405,21 +413,13 @@ func (s *PluginScanner) validateSignature(plugin *PluginBase) *PluginError { |
|
|
|
|
|
|
|
|
|
switch plugin.Signature { |
|
|
|
|
case PluginSignatureUnsigned: |
|
|
|
|
allowUnsigned := false |
|
|
|
|
for _, plug := range s.cfg.PluginsAllowUnsigned { |
|
|
|
|
if plug == plugin.Id { |
|
|
|
|
allowUnsigned = true |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if setting.Env != setting.Dev && !allowUnsigned { |
|
|
|
|
if allowed := s.allowUnsigned(plugin); !allowed { |
|
|
|
|
s.log.Debug("Plugin is unsigned", "id", plugin.Id) |
|
|
|
|
s.errors = append(s.errors, fmt.Errorf("plugin %q is unsigned", plugin.Id)) |
|
|
|
|
return &PluginError{ |
|
|
|
|
ErrorCode: signatureMissing, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
s.log.Warn("Running an unsigned backend plugin", "pluginID", plugin.Id, "pluginDir", |
|
|
|
|
plugin.PluginDir) |
|
|
|
|
return nil |
|
|
|
|
@ -440,6 +440,24 @@ func (s *PluginScanner) validateSignature(plugin *PluginBase) *PluginError { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (s *PluginScanner) allowUnsigned(plugin *PluginBase) bool { |
|
|
|
|
if s.allowUnsignedPluginsCondition != nil { |
|
|
|
|
return s.allowUnsignedPluginsCondition(plugin) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if setting.Env == setting.Dev { |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for _, plug := range s.cfg.PluginsAllowUnsigned { |
|
|
|
|
if plug == plugin.Id { |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func ScanningErrors() []PluginError { |
|
|
|
|
scanningErrs := make([]PluginError, 0) |
|
|
|
|
for id, e := range pluginScanningErrors { |
|
|
|
|
|