Allow feature.yml to change available subcommands (#2156)
This commit is contained in:
parent
3fa555fb25
commit
38ab6be7c2
9 changed files with 57 additions and 46 deletions
|
@ -209,6 +209,21 @@ It is meant to allow you to manage bans, parsers/scenarios/etc, api and generall
|
|||
log.Fatalf("failed to hide flag: %s", err)
|
||||
}
|
||||
|
||||
// Look for "-c /path/to/config.yaml"
|
||||
// This duplicates the logic in cobra, but we need to do it before
|
||||
// because feature flags can change which subcommands are available.
|
||||
for i, arg := range os.Args {
|
||||
if arg == "-c" || arg == "--config" {
|
||||
if len(os.Args) > i+1 {
|
||||
ConfigFilePath = os.Args[i+1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := csconfig.LoadFeatureFlagsFile(ConfigFilePath, log.StandardLogger()); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if len(os.Args) > 1 {
|
||||
cobra.OnInitialize(initConfig)
|
||||
}
|
||||
|
@ -249,7 +264,6 @@ It is meant to allow you to manage bans, parsers/scenarios/etc, api and generall
|
|||
}
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
log.NewEntry(log.StandardLogger()).Log(log.FatalLevel, err)
|
||||
os.Exit(1)
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -191,9 +191,14 @@ func newLogLevel(curLevelPtr *log.Level, f *Flags) *log.Level {
|
|||
}
|
||||
|
||||
// LoadConfig returns a configuration parsed from configuration file
|
||||
func LoadConfig(cConfig *csconfig.Config) error {
|
||||
func LoadConfig(configFile string, disableAgent bool, disableAPI bool, quiet bool) (*csconfig.Config, error) {
|
||||
cConfig, err := csconfig.NewConfig(configFile, disableAgent, disableAPI, quiet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if (cConfig.Common == nil || *cConfig.Common == csconfig.CommonCfg{}) {
|
||||
return fmt.Errorf("unable to load configuration: common section is empty")
|
||||
return nil, fmt.Errorf("unable to load configuration: common section is empty")
|
||||
}
|
||||
|
||||
cConfig.Common.LogLevel = newLogLevel(cConfig.Common.LogLevel, flags)
|
||||
|
@ -207,7 +212,7 @@ func LoadConfig(cConfig *csconfig.Config) error {
|
|||
|
||||
// Configuration paths are dependency to load crowdsec configuration
|
||||
if err := cConfig.LoadConfigurationPaths(); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if flags.SingleFileType != "" && flags.OneShotDSN != "" {
|
||||
|
@ -221,31 +226,31 @@ func LoadConfig(cConfig *csconfig.Config) error {
|
|||
cConfig.Common.LogMaxSize, cConfig.Common.LogMaxFiles,
|
||||
cConfig.Common.LogMaxAge, cConfig.Common.CompressLogs,
|
||||
cConfig.Common.ForceColorLogs); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := csconfig.LoadFeatureFlagsFile(cConfig, log.StandardLogger()); err != nil {
|
||||
return err
|
||||
if err := csconfig.LoadFeatureFlagsFile(configFile, log.StandardLogger()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !flags.DisableAgent {
|
||||
if err := cConfig.LoadCrowdsec(); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if !flags.DisableAPI {
|
||||
if err := cConfig.LoadAPIServer(); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if !cConfig.DisableAgent && (cConfig.API == nil || cConfig.API.Client == nil || cConfig.API.Client.Credentials == nil) {
|
||||
return errors.New("missing local API credentials for crowdsec agent, abort")
|
||||
return nil, errors.New("missing local API credentials for crowdsec agent, abort")
|
||||
}
|
||||
|
||||
if cConfig.DisableAPI && cConfig.DisableAgent {
|
||||
return errors.New("You must run at least the API Server or crowdsec")
|
||||
return nil, errors.New("You must run at least the API Server or crowdsec")
|
||||
}
|
||||
|
||||
if flags.TestMode && !cConfig.DisableAgent {
|
||||
|
@ -253,15 +258,15 @@ func LoadConfig(cConfig *csconfig.Config) error {
|
|||
}
|
||||
|
||||
if flags.OneShotDSN != "" && flags.SingleFileType == "" {
|
||||
return errors.New("-dsn requires a -type argument")
|
||||
return nil, errors.New("-dsn requires a -type argument")
|
||||
}
|
||||
|
||||
if flags.Transform != "" && flags.OneShotDSN == "" {
|
||||
return errors.New("-transform requires a -dsn argument")
|
||||
return nil, errors.New("-transform requires a -dsn argument")
|
||||
}
|
||||
|
||||
if flags.SingleFileType != "" && flags.OneShotDSN == "" {
|
||||
return errors.New("-type requires a -dsn argument")
|
||||
return nil, errors.New("-type requires a -dsn argument")
|
||||
}
|
||||
|
||||
if flags.SingleFileType != "" && flags.OneShotDSN != "" {
|
||||
|
@ -290,7 +295,7 @@ func LoadConfig(cConfig *csconfig.Config) error {
|
|||
log.Infof("Enabled feature flags: %s", fflist)
|
||||
}
|
||||
|
||||
return nil
|
||||
return cConfig, nil
|
||||
}
|
||||
|
||||
// crowdsecT0 can be used to measure start time of services,
|
||||
|
|
|
@ -34,11 +34,7 @@ func StartRunSvc() error {
|
|||
},
|
||||
})
|
||||
|
||||
cConfig, err = csconfig.NewConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := LoadConfig(cConfig); err != nil {
|
||||
if cConfig, err = LoadConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI, false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -61,13 +61,10 @@ func WindowsRun() error {
|
|||
err error
|
||||
)
|
||||
|
||||
cConfig, err = csconfig.NewConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI, false)
|
||||
cConfig, err = LoadConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := LoadConfig(cConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
// Configure logging
|
||||
log.Infof("Crowdsec %s", cwversion.VersionStr())
|
||||
|
||||
|
|
|
@ -54,15 +54,11 @@ func reloadHandler(sig os.Signal) (*csconfig.Config, error) {
|
|||
crowdsecTomb = tomb.Tomb{}
|
||||
pluginTomb = tomb.Tomb{}
|
||||
|
||||
cConfig, err := csconfig.NewConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI, false)
|
||||
cConfig, err := LoadConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = LoadConfig(cConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !cConfig.DisableAPI {
|
||||
if flags.DisableCAPI {
|
||||
log.Warningf("Communication with CrowdSec Central API disabled from args")
|
||||
|
|
|
@ -97,15 +97,11 @@ func runService(name string) error {
|
|||
log.Warnf("Failed to open event log: %s", err)
|
||||
}
|
||||
|
||||
cConfig, err := csconfig.NewConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI, false)
|
||||
cConfig, err := LoadConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := LoadConfig(cConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("starting %s service", name)
|
||||
winsvc := crowdsec_winservice{config: cConfig}
|
||||
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
package csconfig
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
/*cscli specific config, such as hub directory*/
|
||||
type CscliCfg struct {
|
||||
Output string `yaml:"output,omitempty"`
|
||||
|
@ -26,9 +22,6 @@ func (c *Config) LoadCSCLI() error {
|
|||
if err := c.LoadConfigurationPaths(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := LoadFeatureFlagsFile(c, log.StandardLogger()); err != nil {
|
||||
return err
|
||||
}
|
||||
c.Cscli.ConfigDir = c.ConfigPaths.ConfigDir
|
||||
c.Cscli.DataDir = c.ConfigPaths.DataDir
|
||||
c.Cscli.HubDir = c.ConfigPaths.HubDir
|
||||
|
|
|
@ -20,9 +20,12 @@ func LoadFeatureFlagsEnv(logger *log.Logger) error {
|
|||
}
|
||||
|
||||
|
||||
// LoadFeatureFlags parses {ConfigDir}/feature.yaml to enable feature flags.
|
||||
func LoadFeatureFlagsFile(cConfig *Config, logger *log.Logger) error {
|
||||
featurePath := filepath.Join(cConfig.ConfigPaths.ConfigDir, "feature.yaml")
|
||||
// LoadFeatureFlags parses feature.yaml to enable feature flags.
|
||||
// The file is in the same directory as config.yaml, which is provided
|
||||
// as the fist parameter. This can be different than ConfigPaths.ConfigDir
|
||||
func LoadFeatureFlagsFile(configPath string, logger *log.Logger) error {
|
||||
dir := filepath.Dir(configPath)
|
||||
featurePath := filepath.Join(dir, "feature.yaml")
|
||||
|
||||
if err := fflag.Crowdsec.SetFromYamlFile(featurePath, logger); err != nil {
|
||||
return fmt.Errorf("file %s: %s", featurePath, err)
|
||||
|
|
|
@ -282,7 +282,7 @@ teardown() {
|
|||
assert_output - <"$BATS_TEST_DIRNAME"/testdata/explain/explain-log.txt
|
||||
}
|
||||
|
||||
@test "Allow variable expansion and literal \$ characters in passwords' {
|
||||
@test 'Allow variable expansion and literal $ characters in passwords' {
|
||||
export DB_PASSWORD='P@ssw0rd'
|
||||
# shellcheck disable=SC2016
|
||||
config_set '.db_config.password="$DB_PASSWORD"'
|
||||
|
@ -321,3 +321,14 @@ teardown() {
|
|||
rune -0 cscli doc
|
||||
assert_file_exist "doc/cscli_setup.md"
|
||||
}
|
||||
|
||||
@test "feature.yaml for subcommands" {
|
||||
# it is possible to enable subcommands with feature flags defined in feature.yaml
|
||||
|
||||
rune -1 cscli setup
|
||||
assert_stderr --partial 'unknown command \"setup\" for \"cscli\"'
|
||||
CONFIG_DIR=$(dirname "$CONFIG_YAML")
|
||||
echo ' - cscli_setup' >> "$CONFIG_DIR"/feature.yaml
|
||||
rune -0 cscli setup
|
||||
assert_output --partial 'cscli setup [command]'
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue