Merge pull request #35 from HewlettPackard/config_cli

Configuration
This commit is contained in:
Grant Murphy 2016-08-08 08:27:02 -07:00 committed by GitHub
commit 235308f853
17 changed files with 154 additions and 53 deletions

View file

@ -15,13 +15,11 @@
package core
import (
"encoding/json"
"go/ast"
"go/importer"
"go/parser"
"go/token"
"go/types"
"io/ioutil"
"log"
"os"
"reflect"
@ -59,27 +57,19 @@ type Analyzer struct {
Stats Metrics `json:"metrics"`
}
func NewAnalyzer(ignoreNosec bool, conf *string, logger *log.Logger) Analyzer {
func NewAnalyzer(conf map[string]interface{}, logger *log.Logger) Analyzer {
if logger == nil {
logger = log.New(os.Stdout, "[gas]", 0)
}
a := Analyzer{
ignoreNosec: ignoreNosec,
ignoreNosec: conf["ignoreNosec"].(bool),
ruleset: make(RuleSet),
Issues: make([]Issue, 0),
context: Context{token.NewFileSet(), nil, nil, nil, nil, nil},
logger: logger,
}
if conf != nil && *conf != "" { // if we have a config
if data, err := ioutil.ReadFile(*conf); err == nil {
if err := json.Unmarshal(data, &(a.context.Config)); err != nil {
logger.Fatal("Could not parse JSON config: ", *conf, ": ", err)
}
} else {
logger.Fatal("Could not read config file: ", *conf)
}
}
// TODO(tkelsey): use the inc/exc lists
return a
}

61
main.go
View file

@ -15,8 +15,10 @@
package main
import (
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
@ -57,6 +59,51 @@ USAGE:
`
var logger *log.Logger
func extendConfList(conf map[string]interface{}, name string, input []string) {
if val, ok := conf[name]; ok {
if data, ok := val.(*[]string); ok {
conf[name] = append(*data, input...)
} else {
logger.Fatal("Config item must be a string list: ", name)
}
} else {
conf[name] = []string{}
}
}
func buildConfig(incRules string, excRules string) map[string]interface{} {
config := make(map[string]interface{})
if flagConfig != nil && *flagConfig != "" { // parse config if we have one
if data, err := ioutil.ReadFile(*flagConfig); err == nil {
if err := json.Unmarshal(data, &(config)); err != nil {
logger.Fatal("Could not parse JSON config: ", *flagConfig, ": ", err)
}
} else {
logger.Fatal("Could not read config file: ", *flagConfig)
}
}
// add in CLI include and exclude data
extendConfList(config, "include", strings.Split(incRules, ","))
extendConfList(config, "exclude", strings.Split(excRules, ","))
// override ignoreNosec if given on CLI
if flagIgnoreNoSec != nil {
config["ignoreNosec"] = *flagIgnoreNoSec
} else {
val, ok := config["ignoreNosec"]
if !ok {
config["ignoreNosec"] = false
} else if _, ok := val.(bool); !ok {
logger.Fatal("Config value must be a bool: 'ignoreNosec'")
}
}
return config
}
func usage() {
fmt.Fprintln(os.Stderr, usageText)
fmt.Fprint(os.Stderr, "OPTIONS:\n\n")
@ -70,12 +117,18 @@ func main() {
// Exclude files
var excluded filelist = []string{"*_test.go"}
flag.Var(&excluded, "exclude", "File pattern to exclude from scan")
flag.Var(&excluded, "skip", "File pattern to exclude from scan")
// Rule configuration
rules := newRulelist()
flag.Var(&rules, "rule", "GAS rules enabled when performing a scan")
incRules := ""
flag.StringVar(&incRules, "include", "", "comma sperated list of rules to include")
excRules := ""
flag.StringVar(&excRules, "exclude", "", "comma sperated list of rules to exclude")
// Custom commands / utilities to run instead of default analyzer
tools := newUtils()
flag.Var(tools, "tool", "GAS utilities to assist with rule development")
@ -84,7 +137,7 @@ func main() {
flag.Parse()
// Setup logging
logger := log.New(os.Stderr, "[gas]", log.LstdFlags)
logger = log.New(os.Stderr, "[gas]", log.LstdFlags)
// Ensure at least one file was specified
if flag.NArg() == 0 {
@ -101,7 +154,9 @@ func main() {
}
// Setup analyzer
analyzer := gas.NewAnalyzer(*flagIgnoreNoSec, flagConfig, logger)
config := buildConfig(incRules, excRules)
analyzer := gas.NewAnalyzer(config, logger)
if !rules.overwritten {
rules.useDefaults()
}

View file

@ -21,7 +21,8 @@ import (
)
func TestBind0000(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewBindsToAllNetworkInterfaces())
issues := gasTestRunner(`
@ -42,7 +43,8 @@ func TestBind0000(t *testing.T) {
}
func TestBindEmptyHost(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewBindsToAllNetworkInterfaces())
issues := gasTestRunner(`

View file

@ -21,7 +21,8 @@ import (
)
func TestErrorsMulti(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewNoErrorCheck())
issues := gasTestRunner(
@ -43,7 +44,8 @@ func TestErrorsMulti(t *testing.T) {
}
func TestErrorsSingle(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewNoErrorCheck())
issues := gasTestRunner(
@ -65,7 +67,8 @@ func TestErrorsSingle(t *testing.T) {
}
func TestErrorsGood(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewNoErrorCheck())
issues := gasTestRunner(

View file

@ -21,7 +21,8 @@ import (
)
func TestChmod(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewChmodPerms())
issues := gasTestRunner(`
@ -36,7 +37,8 @@ func TestChmod(t *testing.T) {
}
func TestMkdir(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewMkdirPerms())
issues := gasTestRunner(`

View file

@ -21,7 +21,8 @@ import (
)
func TestHardcoded(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewHardcodedCredentials())
issues := gasTestRunner(

View file

@ -21,7 +21,8 @@ import (
)
func TestHttpoxy(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewBlacklistImports())
issues := gasTestRunner(`

View file

@ -21,7 +21,8 @@ import (
)
func TestNosec(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSubproc())
issues := gasTestRunner(
@ -39,7 +40,8 @@ func TestNosec(t *testing.T) {
}
func TestNosecBlock(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSubproc())
issues := gasTestRunner(
@ -58,3 +60,22 @@ func TestNosecBlock(t *testing.T) {
checkTestResults(t, issues, 0, "None")
}
func TestNosecIgnore(t *testing.T) {
config := map[string]interface{}{"ignoreNosec": true}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSubproc())
issues := gasTestRunner(
`package main
import (
"fmt"
)
func main() {
cmd := exec.Command("sh", "-c", config.Command) // #nosec
}`, analyzer)
checkTestResults(t, issues, 1, "Subprocess launching with variable.")
}

View file

@ -21,7 +21,8 @@ import (
)
func TestRandOk(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewWeakRandCheck())
issues := gasTestRunner(
@ -38,7 +39,8 @@ func TestRandOk(t *testing.T) {
}
func TestRandBad(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewWeakRandCheck())
issues := gasTestRunner(

View file

@ -21,7 +21,8 @@ import (
)
func TestRSAKeys(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewWeakKeyStrength())
issues := gasTestRunner(

View file

@ -21,7 +21,8 @@ import (
)
func TestSQLInjectionViaConcatenation(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSqlStrConcat())
source := `
@ -48,7 +49,8 @@ func TestSQLInjectionViaConcatenation(t *testing.T) {
}
func TestSQLInjectionViaIntepolation(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSqlStrFormat())
source := `
@ -77,7 +79,8 @@ func TestSQLInjectionViaIntepolation(t *testing.T) {
}
func TestSQLInjectionFalsePositiveA(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSqlStrConcat())
analyzer.AddRule(NewSqlStrFormat())
@ -112,7 +115,8 @@ func TestSQLInjectionFalsePositiveA(t *testing.T) {
}
func TestSQLInjectionFalsePositiveB(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSqlStrConcat())
analyzer.AddRule(NewSqlStrFormat())
@ -147,7 +151,8 @@ func TestSQLInjectionFalsePositiveB(t *testing.T) {
}
func TestSQLInjectionFalsePositiveC(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSqlStrConcat())
analyzer.AddRule(NewSqlStrFormat())
@ -182,7 +187,8 @@ func TestSQLInjectionFalsePositiveC(t *testing.T) {
}
func TestSQLInjectionFalsePositiveD(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSqlStrConcat())
analyzer.AddRule(NewSqlStrFormat())

View file

@ -21,7 +21,8 @@ import (
)
func TestSubprocess(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSubproc())
issues := gasTestRunner(`
@ -48,7 +49,8 @@ func TestSubprocess(t *testing.T) {
}
func TestSubprocessVar(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSubproc())
issues := gasTestRunner(`
@ -75,7 +77,8 @@ func TestSubprocessVar(t *testing.T) {
}
func TestSubprocessPath(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSubproc())
issues := gasTestRunner(`
@ -101,7 +104,8 @@ func TestSubprocessPath(t *testing.T) {
}
func TestSubprocessSyscall(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewSubproc())
issues := gasTestRunner(`

View file

@ -21,7 +21,8 @@ import (
)
func TestTempfiles(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewBadTempFile())
source := `

View file

@ -21,7 +21,8 @@ import (
)
func TestTemplateCheckSafe(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewTemplateCheck())
source := `
@ -48,7 +49,8 @@ func TestTemplateCheckSafe(t *testing.T) {
}
func TestTemplateCheckBadHTML(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewTemplateCheck())
source := `
@ -76,7 +78,8 @@ func TestTemplateCheckBadHTML(t *testing.T) {
}
func TestTemplateCheckBadJS(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewTemplateCheck())
source := `
@ -104,7 +107,8 @@ func TestTemplateCheckBadJS(t *testing.T) {
}
func TestTemplateCheckBadURL(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewTemplateCheck())
source := `

View file

@ -21,7 +21,8 @@ import (
)
func TestInsecureSkipVerify(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewModernTlsCheck())
issues := gasTestRunner(`
@ -49,7 +50,8 @@ func TestInsecureSkipVerify(t *testing.T) {
}
func TestInsecureMinVersion(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewModernTlsCheck())
issues := gasTestRunner(`
@ -77,7 +79,8 @@ func TestInsecureMinVersion(t *testing.T) {
}
func TestInsecureMaxVersion(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewModernTlsCheck())
issues := gasTestRunner(`
@ -105,7 +108,8 @@ func TestInsecureMaxVersion(t *testing.T) {
}
func TestInsecureCipherSuite(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewModernTlsCheck())
issues := gasTestRunner(`

View file

@ -21,7 +21,8 @@ import (
)
func TestUnsafe(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewUsingUnsafe())
issues := gasTestRunner(`

View file

@ -21,7 +21,8 @@ import (
)
func TestMD5(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewBlacklistImports())
analyzer.AddRule(NewUsesWeakCryptography())
@ -42,7 +43,8 @@ func TestMD5(t *testing.T) {
}
func TestDES(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewBlacklistImports())
analyzer.AddRule(NewUsesWeakCryptography())
@ -81,7 +83,8 @@ func TestDES(t *testing.T) {
}
func TestRC4(t *testing.T) {
analyzer := gas.NewAnalyzer(false, nil, nil)
config := map[string]interface{}{"ignoreNosec": false}
analyzer := gas.NewAnalyzer(config, nil)
analyzer.AddRule(NewBlacklistImports())
analyzer.AddRule(NewUsesWeakCryptography())