From 8b030569771fa8193e488d5e35815f1689698154 Mon Sep 17 00:00:00 2001 From: jake Date: Tue, 11 Nov 2025 23:44:38 -0500 Subject: [PATCH] updates - moving cpus to string to allow for env vars and other config options besides hardcoded floats --- compose/compose.go | 2 +- issue/issue.go | 10 ++++++++++ main.go | 46 +++++++++++++++++++++++----------------------- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/compose/compose.go b/compose/compose.go index dc3106b..cfe3772 100644 --- a/compose/compose.go +++ b/compose/compose.go @@ -13,7 +13,7 @@ type DeployConfig struct { type ServiceConfig struct { MemLimit *string `yaml:"mem_limit"` - Cpus *float64 `yaml:"cpus"` + Cpus *string `yaml:"cpus"` Ports *[]string `yaml:"ports"` User *string `yaml:"user"` Deploy *DeployConfig `yaml:"deploy"` diff --git a/issue/issue.go b/issue/issue.go index b44af5d..6ac36c2 100644 --- a/issue/issue.go +++ b/issue/issue.go @@ -28,3 +28,13 @@ func (i *Issue) Fatal() { i.Level = FATAL i.Safe = false } + +func (i *Issue) Serious() { + if i.Level == FATAL { + return + } else if i.Level == WARNING { + i.Level = FATAL + } else if i.Level == PASSED { + i.Level = WARNING + } +} diff --git a/main.go b/main.go index 48d75fc..bdcb142 100644 --- a/main.go +++ b/main.go @@ -21,7 +21,8 @@ const ( ROOT_USER = "1000" ROOT_GROUP = "1000" //this is an insane regex to detect IP:PORT:PORT in port configuration but also supports the ability to detect secrets.* and vars.* from workflows - IM_SO_SORRY = `^(\${\s*\w+\s*}|[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}){1}:(\${\s*\w+\s*}|[0-9]+){1}:(\${\s*\w+\s*}|[0-9]+){1}$` + IP_PORT_PORT_REGEX = `^(\${\s*\w+\s*}|[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}){1}:(\${\s*\w+\s*}|[0-9]+){1}:(\${\s*\w+\s*}|[0-9]+){1}$` + ENV_PORT_PORT = `^\${\s*\w+\s*}{1}:\${\s*\w+\s*}{1}$` ) func main() { @@ -57,17 +58,17 @@ func main() { Name: name, } - i := ResourceCheck(serviceConf) + i := ResourceCheck(&serviceConf) if i != nil { rprt.Issues = append(rprt.Issues, i) } - j := SecurityOptCheck(serviceConf) + j := SecurityOptCheck(&serviceConf) if j != nil { rprt.Issues = append(rprt.Issues, j) } - k, err := UserCheck(serviceConf) + k, err := UserCheck(&serviceConf) if err != nil { log.Fatal(err) } @@ -75,7 +76,7 @@ func main() { rprt.Issues = append(rprt.Issues, k) } - l, err := PortCheck(serviceConf) + l, err := PortCheck(&serviceConf) if err != nil { log.Fatal(err) } @@ -83,12 +84,12 @@ func main() { rprt.Issues = append(rprt.Issues, l...) } - m := PolicyCheck(serviceConf) + m := PolicyCheck(&serviceConf) if m != nil { rprt.Issues = append(rprt.Issues, m) } - n := PrivilegedCheck(serviceConf) + n := PrivilegedCheck(&serviceConf) if n != nil { rprt.Issues = append(rprt.Issues, n) } @@ -96,7 +97,6 @@ func main() { issues = append(issues, rprt) } - //this is better printing, it should probably group up the port issues in a better printing. Not sure how lvl := os.Getenv("LOG_LEVEL") fatalCount := 0 for _, p := range issues { @@ -123,21 +123,21 @@ func main() { } // ensure cpus and mem_limit are set on the service -func ResourceCheck(srv compose.ServiceConfig) *issue.Issue { +func ResourceCheck(srv *compose.ServiceConfig) *issue.Issue { i := &issue.Issue{} if srv.Cpus == nil { i.Warning() - i.Messages = append(i.Messages, "there is no cpu limit set for the service") + i.Messages = append(i.Messages, "there is no cpu limit set for the service, set cpus to define the number of (potentially virtual) CPUs to allocate to service containers") } if srv.MemLimit == nil { i.Warning() - i.Messages = append(i.Messages, "there is no memory limit set for the service") + i.Messages = append(i.Messages, "there is no memory limit set for the service, set mem_limit to configure a limit on the amount of memory a container can allocate") } if srv.Cpus == nil && srv.MemLimit == nil { i.Fatal() - i.Messages = append(i.Messages, "there are no resource limits set for the service") + i.Messages = append(i.Messages, "there are no resource limits set for the service, its the wild west") } if len(i.Messages) > 0 { @@ -145,12 +145,12 @@ func ResourceCheck(srv compose.ServiceConfig) *issue.Issue { } i.Passed() - i.Messages = append(i.Messages, "resource limits configuration is safe") + i.Messages = append(i.Messages, "resource limits are configured properly") return i } // make sure service is not ran as privileged -func PrivilegedCheck(srv compose.ServiceConfig) *issue.Issue { +func PrivilegedCheck(srv *compose.ServiceConfig) *issue.Issue { i := &issue.Issue{} if srv.Privileged == nil { i.Passed() @@ -160,7 +160,7 @@ func PrivilegedCheck(srv compose.ServiceConfig) *issue.Issue { if *srv.Privileged == true { i.Fatal() - i.Messages = append(i.Messages, "privileged flag is set to true") + i.Messages = append(i.Messages, "privileged flag is set to true, remove it to prevent the service container from running with elevated privileges") return i } @@ -170,11 +170,11 @@ func PrivilegedCheck(srv compose.ServiceConfig) *issue.Issue { } // checks for specific security options -func SecurityOptCheck(srv compose.ServiceConfig) *issue.Issue { +func SecurityOptCheck(srv *compose.ServiceConfig) *issue.Issue { i := &issue.Issue{} if srv.SecOpts == nil { i.Fatal() - i.Messages = append(i.Messages, "set no-new-privileges=true on the service security_opts") + i.Messages = append(i.Messages, "set no-new-privileges=true on the service security_opts to disable container processes from gaining new privileges") return i } @@ -187,12 +187,12 @@ func SecurityOptCheck(srv compose.ServiceConfig) *issue.Issue { } i.Fatal() - i.Messages = append(i.Messages, "set no-new-privileges=true on the container security_opts") + i.Messages = append(i.Messages, "set no-new-privileges=true on the container security_opts to disable container processes from gaining new privileges") return i } // checking port to ensure it is behind a reverse proxy -func PortCheck(srv compose.ServiceConfig) ([]*issue.Issue, error) { +func PortCheck(srv *compose.ServiceConfig) ([]*issue.Issue, error) { il := []*issue.Issue{} if srv.Ports == nil { i := &issue.Issue{} @@ -216,7 +216,7 @@ func PortCheck(srv compose.ServiceConfig) ([]*issue.Issue, error) { continue } - ms, err := regexp.Match(`^\${\s*\w+\s*}{1}:\${\s*\w+\s*}{1}$`, []byte(prt)) + ms, err := regexp.Match(ENV_PORT_PORT, []byte(prt)) if err != nil { log.Fatal(err) } @@ -228,7 +228,7 @@ func PortCheck(srv compose.ServiceConfig) ([]*issue.Issue, error) { continue } - m2, err := regexp.Match(IM_SO_SORRY, []byte(prt)) + m2, err := regexp.Match(IP_PORT_PORT_REGEX, []byte(prt)) if err != nil { return nil, err } @@ -250,7 +250,7 @@ func PortCheck(srv compose.ServiceConfig) ([]*issue.Issue, error) { } // ensures the user value is set and nonroot in the service -func UserCheck(srv compose.ServiceConfig) (*issue.Issue, error) { +func UserCheck(srv *compose.ServiceConfig) (*issue.Issue, error) { i := &issue.Issue{} if srv.User == nil { i.Warning() @@ -323,7 +323,7 @@ func UserCheck(srv compose.ServiceConfig) (*issue.Issue, error) { } // ensures a restart policy is set in the service configuration with at least max_attempts and restart condition set -func PolicyCheck(srv compose.ServiceConfig) *issue.Issue { +func PolicyCheck(srv *compose.ServiceConfig) *issue.Issue { i := &issue.Issue{} if srv.Deploy != nil { if srv.Deploy.Policy != nil {