fleet/server/service/validation_import_config.go
2017-06-22 15:50:45 -04:00

128 lines
3.8 KiB
Go

package service
import (
"context"
"strconv"
"github.com/kolide/fleet/server/kolide"
)
func (vm validationMiddleware) ImportConfig(ctx context.Context, cfg *kolide.ImportConfig) (*kolide.ImportConfigResponse, error) {
var invalid invalidArgumentError
vm.validateConfigOptions(cfg, &invalid)
vm.validatePacks(cfg, &invalid)
vm.validateDecorator(cfg, &invalid)
vm.validateYARA(cfg, &invalid)
if invalid.HasErrors() {
return nil, invalid
}
return vm.Service.ImportConfig(ctx, cfg)
}
func (vm validationMiddleware) validateYARA(cfg *kolide.ImportConfig, argErrs *invalidArgumentError) {
if cfg.YARA != nil {
if cfg.YARA.FilePaths == nil {
argErrs.Append("yara", "missing file_paths")
return
}
if cfg.YARA.Signatures == nil {
argErrs.Append("yara", "missing signatures")
}
for fileSection, sigs := range cfg.YARA.FilePaths {
if cfg.FileIntegrityMonitoring == nil {
argErrs.Append("yara", "missing file paths section")
return
}
if _, ok := cfg.FileIntegrityMonitoring[fileSection]; !ok {
argErrs.Appendf("yara", "missing referenced file_paths section '%s'", fileSection)
}
for _, sig := range sigs {
if _, ok := cfg.YARA.Signatures[sig]; !ok {
argErrs.Appendf(
"yara",
"missing signature '%s' referenced in '%s'",
sig,
fileSection,
)
}
}
}
}
}
func (vm validationMiddleware) validateDecorator(cfg *kolide.ImportConfig, argErrs *invalidArgumentError) {
if cfg.Decorators != nil {
for str := range cfg.Decorators.Interval {
val, err := strconv.ParseInt(str, 10, 32)
if err != nil {
argErrs.Appendf("decorators", "interval '%s' must be an integer", str)
continue
}
if val%60 != 0 {
argErrs.Appendf("decorators", "interval '%d' must be divisible by 60", val)
}
}
}
}
func (vm validationMiddleware) validateConfigOptions(cfg *kolide.ImportConfig, argErrs *invalidArgumentError) {
if cfg.Options != nil {
for optName, optValue := range cfg.Options {
opt, err := vm.ds.OptionByName(string(optName))
if err != nil {
// skip validation for an option we don't know about, this will generate
// a warning in the service layer
continue
}
if !opt.SameType(optValue) {
argErrs.Appendf("options", "invalid type for '%s'", optName)
}
}
}
}
func (vm validationMiddleware) validatePacks(cfg *kolide.ImportConfig, argErrs *invalidArgumentError) {
if cfg.Packs != nil {
for packName, pack := range cfg.Packs {
// if glob packs is defined we expect at least one external pack
if packName == kolide.GlobPacks {
if len(cfg.GlobPackNames) == 0 {
argErrs.Append("external_packs", "missing glob packs")
continue
}
// make sure that each glob pack has JSON content
for _, p := range cfg.GlobPackNames {
if pd, ok := cfg.ExternalPacks[p]; !ok {
argErrs.Appendf("external_packs", "missing content for '%s'", p)
} else {
vm.validatePackContents(p, pd, argErrs)
}
}
continue
}
// if value is a string we expect a file path, in this case, the user has to supply the
// contents of said file which we store in ExternalPacks, if it's not there we need to
// raise an error
switch val := pack.(type) {
case string:
if pd, ok := cfg.ExternalPacks[packName]; !ok {
argErrs.Appendf("external_packs", "missing content for '%s'", packName)
} else {
vm.validatePackContents(packName, pd, argErrs)
}
case kolide.PackDetails:
vm.validatePackContents(packName, val, argErrs)
}
}
}
}
func (vm validationMiddleware) validatePackContents(packName string, pack kolide.PackDetails, argErrs *invalidArgumentError) {
switch pack.Platform {
case "", "darwin", "freebsd", "windows", "linux", "any", "all":
default:
argErrs.Appendf("pack", "'%s' is not a valid platform", pack.Platform)
}
}