From 990bc2505ac148a8b32f23e5e353b7b0ef60a77c Mon Sep 17 00:00:00 2001 From: Safin Singh <safin.singh@gmail.com> Date: Sun, 29 Oct 2023 23:31:32 -0700 Subject: [PATCH] POC aeaconf integration with obfuscation and sample functions --- checks.go | 89 +++++++++++++++++---------------- checks_linux.go | 8 +-- configs.go | 129 +++++++++++++++++++++++------------------------- go.mod | 14 ++++-- go.sum | 36 +++++++++----- score.go | 5 +- utility.go | 10 ++++ 7 files changed, 158 insertions(+), 133 deletions(-) diff --git a/checks.go b/checks.go index e676430..7aa5181 100644 --- a/checks.go +++ b/checks.go @@ -12,35 +12,21 @@ import ( "reflect" "regexp" "strings" + + "github.com/safinsingh/aeaconf2" ) -// check is the smallest unit that can show up on a scoring report. It holds all -// the conditions for a check, and its message and points (autogenerated or -// otherwise). -type check struct { - Message string - Hint string - Points int - - Fail []cond - Pass []cond - PassOverride []cond -} +var funcRegistry map[string]reflect.Type -// cond, or condition, is the parameters for a given test within a check. -type cond struct { - Hint string - Type string +func init() { + funcRegistry = make(map[string]reflect.Type) - Path string - Cmd string - User string - Group string - Name string - Key string - Value string - After string - regex bool + funcRegistry["AutoCheckUpdatesEnabled"] = reflect.TypeOf(AutoCheckUpdatesEnabled{}) + funcRegistry["DirContains"] = reflect.TypeOf(DirContains{}) + funcRegistry["FileContains"] = reflect.TypeOf(FileContains{}) + funcRegistry["PathExists"] = reflect.TypeOf(PathExists{}) + + aeaconf2.CheckFunctionRegistry(funcRegistry) } // requireArgs is a convenience function that prints a warning if any required @@ -104,11 +90,11 @@ func handleReflectPanic(condFunc string) { } // runCheck executes a single condition check. -func runCheck(cond cond) bool { - if err := deobfuscateCond(&cond); err != nil { +func runCheck(cond aeaconf2.Condition) bool { + if err := deobfuscateCond(cond); err != nil { fail(err.Error()) } - defer obfuscateCond(&cond) + defer obfuscateCond(cond) debug("Running condition:\n", cond) not := "Not" @@ -178,11 +164,15 @@ func (c cond) CommandOutput() (bool, error) { } // DirContains returns true if any file in the directory contains the string value provided. -func (c cond) DirContains() (bool, error) { - c.requireArgs("Path", "Value") - result, err := cond{ - Path: c.Path, - }.PathExists() +type DirContains struct { + aeaconf2.BaseCondition + Path string + Value string + Regex bool +} + +func (d *DirContains) Score() (bool, error) { + result, err := (&PathExists{Path: d.Path}).Score() if err != nil { return false, err } @@ -191,7 +181,7 @@ func (c cond) DirContains() (bool, error) { } var files []string - err = filepath.Walk(c.Path, func(path string, info os.FileInfo, err error) error { + err = filepath.Walk(d.Path, func(path string, info os.FileInfo, err error) error { if !info.IsDir() { files = append(files, path) } @@ -206,8 +196,7 @@ func (c cond) DirContains() (bool, error) { } for _, file := range files { - c.Path = file - result, err := c.FileContains() + result, err := (&FileContains{Path: file, Value: d.Value}).Score() if os.IsPermission(err) { return false, err } @@ -222,21 +211,27 @@ func (c cond) DirContains() (bool, error) { // // Newlines in regex may not work as expected, especially on Windows. It's // best to not use these (ex. ^ and $). -func (c cond) FileContains() (bool, error) { - c.requireArgs("Path", "Value") - fileContent, err := readFile(c.Path) +type FileContains struct { + aeaconf2.BaseCondition + Path string + Value string + Regex bool +} + +func (f *FileContains) Score() (bool, error) { + fileContent, err := readFile(f.Path) if err != nil { return false, err } found := false for _, line := range strings.Split(fileContent, "\n") { - if c.regex { - found, err = regexp.Match(c.Value, []byte(line)) + if f.Regex { + found, err = regexp.Match(f.Value, []byte(line)) if err != nil { return false, err } } else { - found = strings.Contains(line, c.Value) + found = strings.Contains(line, f.Value) } if found { break @@ -264,9 +259,13 @@ func (c cond) FileEquals() (bool, error) { // PathExists is a wrapper around os.Stat and os.IsNotExist, and determines // whether a file or folder exists. -func (c cond) PathExists() (bool, error) { - c.requireArgs("Path") - _, err := os.Stat(c.Path) +type PathExists struct { + aeaconf2.BaseCondition + Path string +} + +func (p *PathExists) Score() (bool, error) { + _, err := os.Stat(p.Path) if err != nil && os.IsNotExist(err) { return false, nil } else if err != nil { diff --git a/checks_linux.go b/checks_linux.go index 519a046..239e091 100644 --- a/checks_linux.go +++ b/checks_linux.go @@ -9,12 +9,14 @@ import ( "syscall" ) -func (c cond) AutoCheckUpdatesEnabled() (bool, error) { - result, err := cond{ +type AutoCheckUpdatesEnabled struct{} + +func (a *AutoCheckUpdatesEnabled) Score() (bool, error) { + result, err := DirContains{ Path: "/etc/apt/apt.conf.d/", Value: `(?i)^\s*APT::Periodic::Update-Package-Lists\s+"1"\s*;\s*$`, regex: true, - }.DirContains() + }.Score() // If /etc/apt/ does not exist, try dnf (RHEL) if err != nil { autoConf, err := cond{ diff --git a/configs.go b/configs.go index 4d1dcab..15becdd 100644 --- a/configs.go +++ b/configs.go @@ -8,6 +8,8 @@ import ( "reflect" "github.com/BurntSushi/toml" + "github.com/safinsingh/aeaconf2" + "github.com/safinsingh/aeaconf2/compat" ) // parseConfig takes the config content as a string and attempts to parse it @@ -17,17 +19,26 @@ func parseConfig(configContent string) { fail("Configuration is empty!") os.Exit(1) } - md, err := toml.Decode(configContent, &conf) + + headerRaw, checksRaw, err := compat.SeparateConfig([]byte(configContent)) if err != nil { - fail("Error decoding TOML: " + err.Error()) + fail("error separating config file: " + err.Error()) os.Exit(1) } - if verboseEnabled { - for _, undecoded := range md.Undecoded() { - warn("Undecoded scoring configuration key \"" + undecoded.String() + "\" will not be used.") - } + + cfg := new(config) + err = toml.Unmarshal(headerRaw, cfg) + if err != nil { + fail("error parsing config file header: " + err.Error()) + os.Exit(1) } + ab := aeaconf2.DefaultAeaconfBuilder(checksRaw, funcRegistry). + SetLineOffset(countLines(headerRaw)). + SetMaxPoints(cfg.MaxPoints) + + cfg.Checks = ab.GetChecks() + // If there's no remote, local must be enabled. if conf.Remote == "" { conf.Local = true @@ -62,19 +73,6 @@ func parseConfig(configContent string) { info("Consider updating your config to include:") info(" version = '" + version + "'") } - - // Print warnings for impossible checks and undefined check types. - for i, check := range conf.Check { - if len(check.Pass) == 0 && len(check.PassOverride) == 0 { - warn("Check " + fmt.Sprintf("%d", i+1) + " does not define any possible ways to pass!") - } - allConditions := append(append(append([]cond{}, check.Pass[:]...), check.Fail[:]...), check.PassOverride[:]...) - for j, cond := range allConditions { - if cond.Type == "" { - warn("Check " + fmt.Sprintf("%d condition %d", i+1, j+1) + " does not have a check type!") - } - } - } } // writeConfig writes the in-memory config to disk as the an encrypted @@ -157,21 +155,8 @@ func printConfig() { if conf.EndDate != "" { pass("End Date:", conf.EndDate) } - for i, check := range conf.Check { - green("CHCK", fmt.Sprintf("Check %d (%d points):", i+1, check.Points)) - fmt.Println("Message:", check.Message) - for _, c := range check.Pass { - fmt.Println("Pass Condition:") - fmt.Print(c) - } - for _, c := range check.PassOverride { - fmt.Println("PassOverride Condition:") - fmt.Print(c) - } - for _, c := range check.Fail { - fmt.Println("Fail Condition:") - fmt.Print(c) - } + for i, check := range conf.Checks { + green("CHCK", fmt.Sprintf("Check %d: %s", i+1, check.Debug())) } } @@ -182,64 +167,72 @@ func obfuscateConfig() { if err := obfuscateData(&conf.Password); err != nil { fail(err.Error()) } - for i, check := range conf.Check { - if err := obfuscateData(&conf.Check[i].Message); err != nil { + for i := range conf.Checks { + if err := obfuscateData(&conf.Checks[i].Message); err != nil { fail(err.Error()) } - if conf.Check[i].Hint != "" { - if err := obfuscateData(&conf.Check[i].Hint); err != nil { - fail(err.Error()) - } - } - for j := range check.Pass { - if err := obfuscateCond(&conf.Check[i].Pass[j]); err != nil { + if conf.Checks[i].Hint != "" { + if err := obfuscateData(&conf.Checks[i].Hint); err != nil { fail(err.Error()) } } - for j := range check.PassOverride { - if err := obfuscateCond(&conf.Check[i].PassOverride[j]); err != nil { - fail(err.Error()) - } - } - for j := range check.Fail { - if err := obfuscateCond(&conf.Check[i].Fail[j]); err != nil { - fail(err.Error()) - } + if err := obfuscateCond(conf.Checks[i].Condition); err != nil { + fail(err.Error()) } } } // obfuscateCond is a convenience function to obfuscate all string fields of a // struct using reflection. It assumes all struct fields are strings. -func obfuscateCond(c *cond) error { + +// ummmmmm +func obfuscateCond(c aeaconf2.Condition) error { s := reflect.ValueOf(c).Elem() + t := s.Type() + for i := 0; i < s.NumField(); i++ { - if s.Type().Field(i).Name == "regex" { - continue - } - datum := s.Field(i).String() - if err := obfuscateData(&datum); err != nil { - return err + field := s.Field(i) + fieldType := t.Field(i).Type + + if fieldType.Kind() == reflect.String { + datum := field.String() + if err := obfuscateData(&datum); err != nil { + return err + } + field.SetString(datum) + } else if fieldType.Implements(reflect.TypeOf((*aeaconf2.Condition)(nil)).Elem()) { + if err := obfuscateCond(field.Addr().Interface().(aeaconf2.Condition)); err != nil { + return err + } } - s.Field(i).SetString(datum) } + return nil } // deobfuscateCond is a convenience function to deobfuscate all string fields // of a struct using reflection. -func deobfuscateCond(c *cond) error { +func deobfuscateCond(c aeaconf2.Condition) error { s := reflect.ValueOf(c).Elem() + t := s.Type() + for i := 0; i < s.NumField(); i++ { - if s.Type().Field(i).Name == "regex" { - continue - } - datum := s.Field(i).String() - if err := deobfuscateData(&datum); err != nil { - return err + field := s.Field(i) + fieldType := t.Field(i).Type + + if fieldType.Kind() == reflect.String { + datum := field.String() + if err := deobfuscateData(&datum); err != nil { + return err + } + field.SetString(datum) + } else if fieldType.Implements(reflect.TypeOf((*aeaconf2.Condition)(nil)).Elem()) { + if err := deobfuscateCond(field.Addr().Interface().(aeaconf2.Condition)); err != nil { + return err + } } - s.Field(i).SetString(datum) } + return nil } diff --git a/go.mod b/go.mod index 24ad882..276515f 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,15 @@ module github.com/elysium-suite/aeacus -go 1.19 +go 1.21.1 + +toolchain go1.21.3 require ( github.com/ActiveState/termtest/conpty v0.5.0 github.com/BurntSushi/toml v1.2.0 github.com/DataDog/datadog-agent/pkg/util/winutil v0.36.1 github.com/creack/pty v1.1.18 - github.com/fatih/color v1.13.0 + github.com/fatih/color v1.15.0 github.com/gen2brain/beeep v0.0.0-20220518085355-d7852edf42fc github.com/gorilla/websocket v1.5.0 github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95 @@ -16,7 +18,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.8.0 github.com/urfave/cli/v2 v2.14.0 - golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 + golang.org/x/sys v0.13.0 golang.org/x/text v0.3.8 ) @@ -32,13 +34,15 @@ require ( github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/google/cabbie v1.0.2 // indirect github.com/google/glazier v0.0.0-20211029225403-9f766cca891d // indirect - github.com/mattn/go-colorable v0.1.9 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/safinsingh/aeaconf2 v0.1.1 github.com/scjalliance/comshim v0.0.0-20190308082608-cf06d2532c4e // indirect github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 895110b..c2ceca8 100644 --- a/go.sum +++ b/go.sum @@ -24,8 +24,8 @@ github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gen2brain/beeep v0.0.0-20220518085355-d7852edf42fc h1:6ZZLxG+lB+Qbg+chtzAEeetwqjlPnY0BXbhL3lQWYOg= @@ -75,12 +75,16 @@ github.com/iamacarpet/go-win64api v0.0.0-20220720120512-241a9064deec/go.mod h1:B github.com/judwhite/go-svc v1.2.1 h1:a7fsJzYUa33sfDJRF2N/WXhA+LonCEEY8BJb1tuS5tA= github.com/judwhite/go-svc v1.2.1/go.mod h1:mo/P2JNX8C07ywpP9YtO2gnBgnUiFTHqtsZekJrUuTk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ= github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -97,6 +101,12 @@ github.com/rickb777/plural v1.2.2/go.mod h1:xyHbelv4YvJE51gjMnHvk+U2e9zIysg6lTnS github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/safinsingh/aeaconf2 v0.0.0-20231030002551-24373810902e h1:1SrqGvirvZudah4mNNslglGwzuNT/Sn09AkNfZ7cOVo= +github.com/safinsingh/aeaconf2 v0.0.0-20231030002551-24373810902e/go.mod h1:U/mGBz9itT5mjn3rDYNckvnrIHNRxzKIoWE8ImDUiFk= +github.com/safinsingh/aeaconf2 v0.1.0 h1:xXcZIOtK/GIzcKO+LWVINCjLgpBv2G3fAUSgjj57goQ= +github.com/safinsingh/aeaconf2 v0.1.0/go.mod h1:U/mGBz9itT5mjn3rDYNckvnrIHNRxzKIoWE8ImDUiFk= +github.com/safinsingh/aeaconf2 v0.1.1 h1:9d5IGHjdh4C4U9WNYKHr66IPS4mos2WRq5AyPRDkZ3g= +github.com/safinsingh/aeaconf2 v0.1.1/go.mod h1:U/mGBz9itT5mjn3rDYNckvnrIHNRxzKIoWE8ImDUiFk= github.com/scjalliance/comshim v0.0.0-20190308082608-cf06d2532c4e h1:+/AzLkOdIXEPrAQtwAeWOBnPQ0BnYlBW0aCZmSb47u4= github.com/scjalliance/comshim v0.0.0-20190308082608-cf06d2532c4e/go.mod h1:9Tc1SKnfACJb9N7cw2eyuI6xzy845G7uZONBsi5uPEA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -126,8 +136,6 @@ golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200428200454-593003d681fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200622182413-4b0db7f3f76b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -140,8 +148,11 @@ golang.org/x/sys v0.0.0-20210601080250-7ecdf8ef093b/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211107104306-e0b2ad06fe42/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY= -golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -159,7 +170,10 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/score.go b/score.go index 5005939..bd3d272 100644 --- a/score.go +++ b/score.go @@ -6,6 +6,8 @@ import ( "log" "os" "strconv" + + "github.com/safinsingh/aeaconf2" ) var ( @@ -74,7 +76,8 @@ type config struct { Title string User string Version string - Check []check + MaxPoints int + Checks []*aeaconf2.Check } // statusRes is to parse a JSON response from the remote server. diff --git a/utility.go b/utility.go index 89cdf68..50f2517 100644 --- a/utility.go +++ b/utility.go @@ -127,6 +127,16 @@ func shellCommandOutput(commandGiven string) (string, error) { return string(out), err } +func countLines(source []byte) int { + ret := 0 + for _, b := range source { + if b == '\n' { + ret++ + } + } + return ret + 1 +} + // assignPoints is used to automatically assign points to checks that don't // have a hardcoded points value. func assignPoints() {