Skip to content

Commit

Permalink
Split regex functions and non-regex functions (#171)
Browse files Browse the repository at this point in the history
* Makes CommandContains regex by default

* Split regex functions and non-regex functions

* Update documentation to reflect what checks have regex support.

* Fix only Regex or only Not bug

* lowercase regex fix

* version bump to 2.1.0

* break to continue
  • Loading branch information
Mobmaker55 authored Aug 22, 2023
1 parent 352572a commit 5f4c9fb
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 74 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ user = "coolUser" # Main user for the image
# if re-used, is compatible with the version of aeacus being used.
#
# You can print your version of aeacus with ./aeacus version.
version = "2.0.6"
version = "2.1.0"

[[check]]
message = "Removed insecure sudoers rule"
Expand Down
54 changes: 29 additions & 25 deletions checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type cond struct {
Key string
Value string
After string
regex bool
}

// requireArgs is a convenience function that prints a warning if any required
Expand All @@ -55,7 +56,7 @@ func (c cond) requireArgs(args ...interface{}) {
v := reflect.ValueOf(c)
vType := v.Type()
for i := 0; i < v.NumField(); i++ {
if vType.Field(i).Name == "Type" {
if vType.Field(i).Name == "Type" || vType.Field(i).Name == "regex" {
continue
}

Expand Down Expand Up @@ -111,21 +112,24 @@ func runCheck(cond cond) bool {
debug("Running condition:\n", cond)

not := "Not"
regex := "Regex"
condFunc := ""
negation := false
cond.regex = false

// Ensure that condition type is a valid length
if len(cond.Type) <= len(not) {
if len(cond.Type) <= len(regex) {
fail(`Condition type "` + cond.Type + `" is not long enough to be valid. Do you have a "type = 'CheckTypeHere'" for all check conditions?`)
return false
}

condEnding := cond.Type[len(cond.Type)-len(not) : len(cond.Type)]
if condEnding == not {
condFunc = cond.Type
if cond.Type[len(cond.Type)-len(not):len(cond.Type)] == not {
negation = true
condFunc = cond.Type[:len(cond.Type)-len(not)]
} else {
condFunc = cond.Type
}
if cond.Type[len(cond.Type)-len(regex):len(cond.Type)] == regex {
cond.regex = true
condFunc = cond.Type[:len(cond.Type)-len(regex)]
}

// Catch panic if check type doesn't exist
Expand All @@ -150,24 +154,30 @@ func runCheck(cond cond) bool {
return err.IsNil() && result
}

// CommandContains checks if a given shell command contains a certain output.
// CommandContains checks if a given shell command contains a certain string.
// This check will always fail if the command returns an error.
func (c cond) CommandContains() (bool, error) {
c.requireArgs("Cmd", "Value")
out, err := shellCommandOutput(c.Cmd)
if err != nil {
return false, err
}
if c.regex {
outTrim := strings.TrimSpace(out)
return regexp.Match(c.Value, []byte(outTrim))
}
return strings.Contains(strings.TrimSpace(out), c.Value), err
}

// CommandOutput checks if a given shell command produces an exact output. This
// check will always fail if the command returns an error.
// CommandOutput checks if a given shell command produces an exact output.
// This check will always fail if the command returns an error.
func (c cond) CommandOutput() (bool, error) {
c.requireArgs("Cmd", "Value")
out, err := shellCommandOutput(c.Cmd)
return strings.TrimSpace(out) == c.Value, err
}

// DirContains returns true if any file in the directory matches the regular
// expression provided.
// 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{
Expand Down Expand Up @@ -208,11 +218,6 @@ func (c cond) DirContains() (bool, error) {
return false, nil
}

// DirContainsRegex is an alias for DirContains
func (c cond) DirContainsRegex() (bool, error) {
return c.DirContains()
}

// FileContains determines whether a file contains a given regular expression.
//
// Newlines in regex may not work as expected, especially on Windows. It's
Expand All @@ -225,9 +230,13 @@ func (c cond) FileContains() (bool, error) {
}
found := false
for _, line := range strings.Split(fileContent, "\n") {
found, err = regexp.Match(c.Value, []byte(line))
if err != nil {
return false, err
if c.regex {
found, err = regexp.Match(c.Value, []byte(line))
if err != nil {
return false, err
}
} else {
found = strings.Contains(line, c.Value)
}
if found {
break
Expand All @@ -236,11 +245,6 @@ func (c cond) FileContains() (bool, error) {
return found, err
}

// FileContainsRegex is an alias for FileContains
func (c cond) FileContainsRegex() (bool, error) {
return c.FileContains()
}

// FileEquals calculates the SHA256 sum of a file and compares it with the hash
// provided in the check.
func (c cond) FileEquals() (bool, error) {
Expand Down
7 changes: 7 additions & 0 deletions checks_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ func (c cond) AutoCheckUpdatesEnabled() (bool, error) {
result, err := cond{
Path: "/etc/apt/apt.conf.d/",
Value: `(?i)^\s*APT::Periodic::Update-Package-Lists\s+"1"\s*;\s*$`,
regex: true,
}.DirContains()
// If /etc/apt/ does not exist, try dnf (RHEL)
if err != nil {
Expand All @@ -26,6 +27,7 @@ func (c cond) AutoCheckUpdatesEnabled() (bool, error) {
applyUpdates, err := cond{
Path: "/etc/dnf/automatic.conf",
Value: `(?i)^\s*apply_updates\s*=\s*(1|on|yes|true)`,
regex: true,
}.FileContains()
if err != nil {
return false, err
Expand Down Expand Up @@ -80,6 +82,7 @@ func (c cond) FirewallUp() (bool, error) {
result, err := cond{
Path: "/etc/ufw/ufw.conf",
Value: `^\s*ENABLED=yes\s*$`,
regex: true,
}.FileContains()
if err != nil {
// If ufw.conf does not exist, check firewalld status (RHEL)
Expand All @@ -95,11 +98,13 @@ func (c cond) GuestDisabledLDM() (bool, error) {
result, err := cond{
Path: "/usr/share/lightdm/lightdm.conf.d/",
Value: guestStr,
regex: true,
}.DirContains()
if !result {
return cond{
Path: "/etc/lightdm/",
Value: guestStr,
regex: true,
}.DirContains()
}
return result, err
Expand Down Expand Up @@ -245,6 +250,7 @@ func (c cond) UserExists() (bool, error) {
return cond{
Path: "/etc/passwd",
Value: "^" + c.User + ":",
regex: true,
}.FileContains()
}

Expand All @@ -253,5 +259,6 @@ func (c cond) UserInGroup() (bool, error) {
return cond{
Path: "/etc/group",
Value: c.Group + `[0-9a-zA-Z,:\s+]+` + c.User,
regex: true,
}.FileContains()
}
6 changes: 6 additions & 0 deletions configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,9 @@ func obfuscateConfig() {
func obfuscateCond(c *cond) error {
s := reflect.ValueOf(c).Elem()
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
Expand All @@ -211,6 +214,9 @@ func obfuscateCond(c *cond) error {
func deobfuscateCond(c *cond) error {
s := reflect.ValueOf(c).Elem()
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
Expand Down
Loading

0 comments on commit 5f4c9fb

Please sign in to comment.