Skip to content

Commit

Permalink
feat: report when no issues are found (#13)
Browse files Browse the repository at this point in the history
* chore: Doing some cleaning up
* feat: announce no issues on clean scan
* feat: add announcement for no results in aws mode

Signed-off-by: Owen Rumney <[email protected]>
  • Loading branch information
owenrumney authored Sep 9, 2022
1 parent 5bcacfd commit 0753bba
Show file tree
Hide file tree
Showing 29 changed files with 320 additions and 259 deletions.
18 changes: 8 additions & 10 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ var defaultConfig *Config
var configPath string

func init() {

homeDir, err := os.UserHomeDir()
if err != nil {
homeDir = os.TempDir()
Expand Down Expand Up @@ -58,40 +57,39 @@ func init() {
_ = os.MkdirAll(lazyTrivyConfigDir, os.ModePerm)

configPath = filepath.Join(lazyTrivyConfigDir, "config.yaml")

}

func Load() (*Config, error) {
logger.Debug("Attempting to load config from %s", configPath)
logger.Debugf("Attempting to load config from %s", configPath)
if _, err := os.Stat(configPath); err != nil {
logger.Debug("No config file found, using defaults")
logger.Debugf("No config file found, using defaults")
return defaultConfig, nil
}

content, err := os.ReadFile(configPath)
if err != nil {
logger.Error("Error reading config file: %s", err)
logger.Errorf("Error reading config file: %s", err)
return defaultConfig, nil
}

if err := yaml.Unmarshal(content, &defaultConfig); err != nil {
logger.Error("Error parsing config file: %s", err)
logger.Errorf("Error parsing config file: %s", err)
return defaultConfig, err
}

return defaultConfig, nil
}

func Save(config *Config) error {
logger.Debug("Saving the config to %s", configPath)
logger.Debugf("Saving the config to %s", configPath)
content, err := yaml.Marshal(config)
if err != nil {
logger.Error("Error marshalling config: %s", err)
logger.Errorf("Error marshalling config: %s", err)
return err
}

if err := os.WriteFile(configPath, content, 0644); err != nil {
logger.Error("Error writing config file: %s", err)
if err := os.WriteFile(configPath, content, 0600); err != nil {
logger.Errorf("Error writing config file: %s", err)
return err
}

Expand Down
48 changes: 24 additions & 24 deletions pkg/controllers/aws/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func NewAWSController(cui *gocui.Gui, dockerClient *docker.Client, cfg *config.C
}

func (c *Controller) Initialise() error {
logger.Debug("Initialising AWS controller")
logger.Debugf("Initialising AWS controller")
var outerErr error

c.Cui.Update(func(gui *gocui.Gui) error {
Expand All @@ -51,13 +51,13 @@ func (c *Controller) Initialise() error {
return err
}

logger.Debug("Configuring keyboard shortcuts")
logger.Debugf("Configuring keyboard shortcuts")
if err := c.configureKeyBindings(); err != nil {
return fmt.Errorf("failed to configure global keys: %w", err)
}

for _, v := range c.Views {
if err := v.ConfigureKeys(); err != nil {
if err := v.ConfigureKeys(gui); err != nil {
return fmt.Errorf("failed to configure view keys: %w", err)
}
}
Expand All @@ -78,13 +78,13 @@ func (c *Controller) Initialise() error {
}

func (c *Controller) refreshServices() error {
logger.Debug("getting caches services")
logger.Debugf("getting caches services")
services, err := c.accountRegionCacheServices(c.Config.AWS.AccountNo, c.Config.AWS.Region)
if err != nil {
return err
}

logger.Debug("Updating the services view with the identified services")
logger.Debugf("Updating the services view with the identified services")
if v, ok := c.Views[widgets.Services].(*widgets.ServicesWidget); ok {
if err := v.RefreshServices(services, 20); err != nil {
return err
Expand All @@ -94,7 +94,7 @@ func (c *Controller) refreshServices() error {
}

func (c *Controller) CreateWidgets(manager base.Manager) error {
logger.Debug("Creating AWS view widgets")
logger.Debugf("Creating AWS view widgets")
menuItems := []string{
"<blue>[?]</blue> help", "s<blue>[w]</blue>itch mode", "<red>[t]</red>erminate scan", "<red>[q]</red>uit",
"\n\n<yellow>Navigation: Use arrow keys to navigate and ESC to exit screens</yellow>",
Expand All @@ -118,7 +118,7 @@ func (c *Controller) CreateWidgets(manager base.Manager) error {
}

func (c *Controller) UpdateAccount(account string) error {
logger.Debug("Updating the AWS account details in the config")
logger.Debugf("Updating the AWS account details in the config")
c.Config.AWS.AccountNo = account
c.Config.AWS.Region = "us-east-1"
if err := c.Config.Save(); err != nil {
Expand All @@ -129,7 +129,7 @@ func (c *Controller) UpdateAccount(account string) error {
}

func (c *Controller) UpdateRegion(region string) error {
logger.Debug("Updating the AWS region details in the config")
logger.Debugf("Updating the AWS region details in the config")
c.Config.AWS.Region = region
if err := c.Config.Save(); err != nil {
return err
Expand All @@ -140,7 +140,7 @@ func (c *Controller) UpdateRegion(region string) error {
func (c *Controller) update() error {
if v, ok := c.Views[widgets.Account]; ok {
if a, ok := v.(*widgets.AccountWidget); ok {
logger.Debug("Updating the AWS account details in the UI")
logger.Debugf("Updating the AWS account details in the UI")
a.UpdateAccount(c.Config.AWS.AccountNo, c.Config.AWS.Region)
if err := c.refreshServices(); err != nil {
return err
Expand Down Expand Up @@ -180,18 +180,18 @@ func (c *Controller) moveViewRight(*gocui.Gui, *gocui.View) error {

func (c *Controller) switchAccount(gui *gocui.Gui, _ *gocui.View) error {

logger.Debug("Switching AWS account")
logger.Debugf("Switching AWS account")
accounts, err := c.listAccountNumbers()
if err != nil {
logger.Error("Failed to list AWS accounts. %s", err)
logger.Errorf("Failed to list AWS accounts. %s", err)
return err
}

x, y := gui.Size()

accountChoices := widgets.NewChoiceWidget("choice", x/2-10, y/2-2, x/2+10, y/2+2, " Choose or ESC ", accounts, c.UpdateAccount, c)
if err := accountChoices.Layout(gui); err != nil {
logger.Error("Failed to create account choice widget. %s", err)
logger.Errorf("Failed to create account choice widget. %s", err)
return fmt.Errorf("error when rendering account choices: %w", err)
}
gui.Update(func(gui *gocui.Gui) error {
Expand All @@ -203,18 +203,18 @@ func (c *Controller) switchAccount(gui *gocui.Gui, _ *gocui.View) error {
}

func (c *Controller) switchRegion(gui *gocui.Gui, _ *gocui.View) error {
logger.Debug("Switching AWS region")
logger.Debugf("Switching AWS region")
regions, err := c.listRegions(c.Config.AWS.AccountNo)
if err != nil {
logger.Error("Failed to list AWS regions. %s", err)
logger.Errorf("Failed to list AWS regions. %s", err)
return err
}

x, y := gui.Size()
regionChoices := widgets.NewChoiceWidget("choice", x/2-10, y/2-2, x/2+10, y/2+len(regions), " Choose or ESC ", regions, c.UpdateRegion, c)

if err := regionChoices.Layout(gui); err != nil {
logger.Error("Failed to create region choice widget. %s", err)
logger.Errorf("Failed to create region choice widget. %s", err)
return fmt.Errorf("error when rendering region choices: %w", err)
}
gui.Update(func(gui *gocui.Gui) error {
Expand All @@ -227,7 +227,7 @@ func (c *Controller) switchRegion(gui *gocui.Gui, _ *gocui.View) error {

func (c *Controller) discoverAccount(region string) (string, string, error) {
ctx := context.Background()
logger.Debug("Loading credentials from default config")
logger.Debugf("Loading credentials from default config")
cfg, err := awsConfig.LoadDefaultConfig(ctx)
if err != nil {
return "", "", err
Expand All @@ -239,21 +239,21 @@ func (c *Controller) discoverAccount(region string) (string, string, error) {
}

if regionEnv, ok := os.LookupEnv("AWS_REGION"); ok {
logger.Debug("Using AWS_REGION environment variable")
logger.Debugf("Using AWS_REGION environment variable")
cfg.Region = regionEnv
}

svc := sts.NewFromConfig(cfg)
result, err := svc.GetCallerIdentity(ctx, &sts.GetCallerIdentityInput{})
if err != nil {
logger.Error("Error getting caller identity")
logger.Errorf("Error getting caller identity")
return "", "", fmt.Errorf("failed to discover AWS caller identity: %w", err)
}
if result.Account == nil {
return "", "", fmt.Errorf("missing account id for aws account")
}

logger.Debug("Discovered AWS account %s", *result.Account)
logger.Debugf("Discovered AWS account %s", *result.Account)
return *result.Account, cfg.Region, nil
}

Expand All @@ -263,7 +263,7 @@ func (c *Controller) scanAccount(gui *gocui.Gui, _ *gocui.View) error {
if err != nil {
if strings.HasPrefix(err.Error(), "failed to discover AWS caller identity") {
c.UpdateStatus("Failed to discover AWS credentials.")
logger.Error("failed to discover AWS credentials: %v", err)
logger.Errorf("failed to discover AWS credentials: %v", err)
return NewErrNoValidCredentials()
}
return err
Expand All @@ -272,7 +272,7 @@ func (c *Controller) scanAccount(gui *gocui.Gui, _ *gocui.View) error {
c.UpdateStatus("Checking credentials for account...")
if account != c.Config.AWS.AccountNo && c.Config.AWS.AccountNo != "" {
c.UpdateStatus("Account number does not match credentials.")
logger.Error("Account number does not match credentials.")
logger.Errorf("Account number does not match credentials.")
return fmt.Errorf("account number mismatch: %s != %s", account, c.Config.AWS.AccountNo)
}

Expand All @@ -293,7 +293,7 @@ func (c *Controller) scanAccount(gui *gocui.Gui, _ *gocui.View) error {

_, _ = gui.SetCurrentView(widgets.Results)
if err := c.refreshServices(); err != nil {
logger.Error("Error refreshing services: %v", err)
logger.Errorf("Error refreshing services: %v", err)
}
c.UpdateStatus("Account scan complete.")
}()
Expand All @@ -313,8 +313,8 @@ func (c *Controller) RenderAWSResultsReport(report *output.Report) error {

func (c *Controller) RenderAWSResultsReportSummary(report *output.Report) error {
if v, ok := c.Views[widgets.Results].(*widgets.AWSResultWidget); ok {
v.UpdateResultsTable([]*output.Report{report})
_, _ = c.Cui.SetCurrentView(widgets.Results)
v.UpdateResultsTable([]*output.Report{report}, c.Cui)

}
return fmt.Errorf("failed to render results report summary") //nolint:goerr113
}
2 changes: 1 addition & 1 deletion pkg/controllers/aws/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func help(gui *gocui.Gui, _ *gocui.View) error {

w, h := gui.Size()

v := widgets.NewHelpWidget("help", w/2-22, h/2-4, w/2+23, h/2+3, helpCommands)
v := widgets.NewAnnouncementWidget("help", "Help", w, h, helpCommands, gui)

if err := gui.SetKeybinding("help", gocui.KeyEsc, gocui.ModNone, func(gui *gocui.Gui, _ *gocui.View) error {
if _, err := gui.SetCurrentView("services"); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/aws/key_bindings.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

func (c *Controller) configureKeyBindings() error {
logger.Debug("Configuring global AWS Controller keyboard shortcuts")
logger.Debugf("Configuring global AWS Controller keyboard shortcuts")
if err := c.ConfigureGlobalKeyBindings(); err != nil {
return fmt.Errorf("error configuring global keybindings: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/aws/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (c *Controller) CancelCurrentScan(_ *gocui.Gui, _ *gocui.View) error {
c.Lock()
defer c.Unlock()
if c.ActiveCancel != nil {
logger.Debug("Cancelling current scan")
logger.Debugf("Cancelling current scan")
c.UpdateStatus("Current scan cancelled.")
c.ActiveCancel()
c.ActiveCancel = nil
Expand Down
25 changes: 4 additions & 21 deletions pkg/controllers/aws/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@ import (
"fmt"
"os"
"path/filepath"
"sync"

"github.com/owenrumney/lazytrivy/pkg/logger"
"github.com/owenrumney/lazytrivy/pkg/output"
)

type state struct {
stateLock sync.Mutex
services []string
selectedService string
serviceWidth int
Expand All @@ -25,7 +23,7 @@ func (s *state) accountRegionCache(accountID, region string) string {
}

func (s *state) listAccountNumbers() ([]string, error) {
logger.Debug("listing account numbers")
logger.Debugf("listing account numbers")
var accountNumbers []string
fileInfos, err := os.ReadDir(s.cacheDirectory)
if err != nil {
Expand All @@ -40,7 +38,7 @@ func (s *state) listAccountNumbers() ([]string, error) {
}

func (s *state) listRegions(accountNumber string) ([]string, error) {
logger.Debug("listing regions")
logger.Debugf("listing regions")
var regions []string
accountPath := filepath.Join(s.cacheDirectory, accountNumber)
fileInfos, err := os.ReadDir(accountPath)
Expand All @@ -59,7 +57,7 @@ func (s *state) accountRegionCacheExists(accountID, region string) bool {
if _, err := os.Stat(s.accountRegionCache(accountID, region)); err == nil {
return true
}
logger.Debug("cache does not exist for %s (%s)", accountID, region)
logger.Debugf("cache does not exist for %s (%s)", accountID, region)
return false
}

Expand Down Expand Up @@ -93,21 +91,6 @@ func (s *state) accountRegionCacheServices(accountID, region string) ([]string,
return services, nil
}

func (s *state) updateServices(services []string) {
s.stateLock.Lock()
defer s.stateLock.Unlock()
s.services = services

s.serviceWidth = getLongestName(services)
s.selectedService = ""
}

func (s *state) setSelected(selectedImage string) {
s.stateLock.Lock()
defer s.stateLock.Unlock()
s.selectedService = selectedImage
}

func (s *state) getServiceReport(accountID, region, serviceName string) (*output.Report, error) {
cachePath := s.accountRegionCache(accountID, region)

Expand All @@ -120,7 +103,7 @@ func (s *state) getServiceReport(accountID, region, serviceName string) (*output

var report output.Report
if err := json.Unmarshal(content, &report); err != nil {
logger.Error("failed to unmarshal report: %s", err)
logger.Errorf("failed to unmarshal report: %s", err)
return nil, err
}
report.Process()
Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/base/global_keybindings.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
)

func (c *Controller) ConfigureGlobalKeyBindings() error {
logger.Debug("Configuring global keyboard shortcuts")
logger.Debugf("Configuring global keyboard shortcuts")

if err := c.Cui.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, Quit); err != nil {
return fmt.Errorf("error setting keybinding for quitting with Ctrl+C: %w", err)
Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/gui/gui.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type Controller struct {
}

func New() (*Controller, error) {
logger.Debug("Creating GUI")
logger.Debugf("Creating GUI")
cui, err := gocui.NewGui(gocui.OutputNormal, true)
if err != nil {
return nil, fmt.Errorf("failed to create gui: %w", err)
Expand Down
11 changes: 1 addition & 10 deletions pkg/controllers/vulnerabilities/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,7 @@ func help(gui *gocui.Gui, _ *gocui.View) error {

w, h := gui.Size()

v := widgets.NewHelpWidget("help", w/2-22, h/2-4, w/2+22, h/2+4, helpCommands)

if err := gui.SetKeybinding("help", gocui.KeyEsc, gocui.ModNone, func(gui *gocui.Gui, _ *gocui.View) error {
if _, err := gui.SetCurrentView("images"); err != nil {
return err
}
return gui.DeleteView("help")
}); err != nil {
return err
}
v := widgets.NewAnnouncementWidget("help", "Help", w, h, helpCommands, gui)

gui.Update(func(g *gocui.Gui) error {
if err := v.Layout(g); err != nil {
Expand Down
Loading

0 comments on commit 0753bba

Please sign in to comment.