Skip to content

Commit

Permalink
fix(scan): enable to report if some warnings occured on scanning (#805)
Browse files Browse the repository at this point in the history
* fix(scan): enable to report if some warnings occured on scanning

* alpine, debian, freebsd, suse

* -format-full-text, -format-list, -format-one-line-text

* implement slack.go

* implement tui.go

* go fmt
  • Loading branch information
kotakanbe authored Jun 12, 2019
1 parent abcea1a commit 17bb575
Show file tree
Hide file tree
Showing 11 changed files with 163 additions and 93 deletions.
8 changes: 8 additions & 0 deletions commands/tui.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,5 +245,13 @@ func (p *TuiCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) s
util.Log.Error(err)
return subcommands.ExitFailure
}

for _, r := range res {
if len(r.Warnings) != 0 {
util.Log.Warnf("Warning: Some warnings occurred while scanning on %s: %s",
r.FormatServerName(), r.Warnings)
}
}

return report.RunTui(res)
}
4 changes: 4 additions & 0 deletions models/scanresults.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ type ScanResult struct {
ReportedRevision string `json:"reportedRevision"`
ReportedBy string `json:"reportedBy"`
Errors []string `json:"errors"`
Warnings []string `json:"warnings"`

ScannedCves VulnInfos `json:"scannedCves"`
RunningKernel Kernel `json:"runningKernel"`
Expand Down Expand Up @@ -319,6 +320,9 @@ func (r ScanResult) ServerInfoTui() string {
if len(r.Container.ContainerID) == 0 {
line := fmt.Sprintf("%s (%s%s)",
r.ServerName, r.Family, r.Release)
if len(r.Warnings) != 0 {
line = "[Warn] " + line
}
if r.RunningKernel.RebootRequired {
return "[Reboot] " + line
}
Expand Down
80 changes: 29 additions & 51 deletions report/slack.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,58 +74,60 @@ func (w SlackWriter) Write(rs ...models.ScanResult) (err error) {
}
sort.Ints(chunkKeys)

summary := fmt.Sprintf("%s\n%s",
getNotifyUsers(config.Conf.Slack.NotifyUsers),
formatOneLineSummary(r))

// Send slack by API
if 0 < len(token) {
api := slack.New(token)
ParentMsg := slack.PostMessageParameters{
// Text: msgText(r),
msgPrms := slack.PostMessageParameters{
Username: conf.AuthUser,
IconEmoji: conf.IconEmoji,
}

if config.Conf.FormatOneLineText {
if _, _, err = api.PostMessage(channel, formatOneLineSummary(r), ParentMsg); err != nil {
return err
}
continue
}

var ts string
if _, ts, err = api.PostMessage(channel, msgText(r), ParentMsg); err != nil {
if _, ts, err = api.PostMessage(channel,
summary, msgPrms); err != nil {
return err
}

if config.Conf.FormatOneLineText || 0 < len(r.Errors) {
continue
}

for _, k := range chunkKeys {
params := slack.PostMessageParameters{
// Text: msgText(r),
Username: conf.AuthUser,
IconEmoji: conf.IconEmoji,
Attachments: m[k],
ThreadTimestamp: ts,
}
if _, _, err = api.PostMessage(channel, msgText(r), params); err != nil {
if _, _, err = api.PostMessage(channel, "", params); err != nil {
return err
}
}
} else {
if config.Conf.FormatOneLineText {
msg := message{
Text: formatOneLineSummary(r),
Username: conf.AuthUser,
IconEmoji: conf.IconEmoji,
Channel: channel,
}
if err := send(msg); err != nil {
return err
}
msg := message{
Text: summary,
Username: conf.AuthUser,
IconEmoji: conf.IconEmoji,
Channel: channel,
}
if err := send(msg); err != nil {
return err
}

if config.Conf.FormatOneLineText || 0 < len(r.Errors) {
continue
}

for i, k := range chunkKeys {
txt := ""
if i == 0 {
txt = msgText(r)
}
for _, k := range chunkKeys {
txt := fmt.Sprintf("%d/%d for %s",
k+1,
len(chunkKeys),
r.FormatServerName())

msg := message{
Text: txt,
Username: conf.AuthUser,
Expand Down Expand Up @@ -176,30 +178,6 @@ func send(msg message) error {
return nil
}

func msgText(r models.ScanResult) string {
notifyUsers := ""
if 0 < len(r.ScannedCves) {
notifyUsers = getNotifyUsers(config.Conf.Slack.NotifyUsers)
}
serverInfo := fmt.Sprintf("*%s*", r.ServerInfo())

if 0 < len(r.Errors) {
return fmt.Sprintf("%s\n%s\n%s\n%s\n%s\nError: %s",
notifyUsers,
serverInfo,
r.ScannedCves.FormatCveSummary(),
r.ScannedCves.FormatFixedStatus(r.Packages),
r.FormatUpdatablePacksSummary(),
r.Errors)
}
return fmt.Sprintf("%s\n%s\n%s\n%s\n%s",
notifyUsers,
serverInfo,
r.ScannedCves.FormatCveSummary(),
r.ScannedCves.FormatFixedStatus(r.Packages),
r.FormatUpdatablePacksSummary())
}

func toSlackAttachments(r models.ScanResult) (attaches []slack.Attachment) {
vinfos := r.ScannedCves.ToSortedSlice()
for _, vinfo := range vinfos {
Expand Down
39 changes: 33 additions & 6 deletions report/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ func formatScanSummary(rs ...models.ScanResult) string {
table := uitable.New()
table.MaxColWidth = maxColWidth
table.Wrap = true

warnMsgs := []string{}
for _, r := range rs {
var cols []interface{}
if len(r.Errors) == 0 {
Expand All @@ -57,18 +59,26 @@ func formatScanSummary(rs ...models.ScanResult) string {
r.FormatServerName(),
"Error",
"",
"Run with --debug to view the details",
"Use configtest subcommand or scan with --debug to view the details",
}
}
table.AddRow(cols...)

if len(r.Warnings) != 0 {
warnMsgs = append(warnMsgs, fmt.Sprintf("Warning for %s: %s",
r.FormatServerName(), r.Warnings))
}
}
return fmt.Sprintf("%s\n", table)
return fmt.Sprintf("%s\n\n%s", table, strings.Join(
warnMsgs, "\n\n"))
}

func formatOneLineSummary(rs ...models.ScanResult) string {
table := uitable.New()
table.MaxColWidth = maxColWidth
table.Wrap = true

warnMsgs := []string{}
for _, r := range rs {
var cols []interface{}
if len(r.Errors) == 0 {
Expand All @@ -83,22 +93,33 @@ func formatOneLineSummary(rs ...models.ScanResult) string {
} else {
cols = []interface{}{
r.FormatServerName(),
"Error: Scan with --debug to view the details",
"Use configtest subcommand or scan with --debug to view the details",
"",
}
}
table.AddRow(cols...)

if len(r.Warnings) != 0 {
warnMsgs = append(warnMsgs, fmt.Sprintf("Warning for %s: %s",
r.FormatServerName(), r.Warnings))
}
}
return fmt.Sprintf("%s\n", table)
return fmt.Sprintf("%s\n\n%s", table, strings.Join(
warnMsgs, "\n\n"))
}

func formatList(r models.ScanResult) string {
header := r.FormatTextReportHeadedr()
if len(r.Errors) != 0 {
return fmt.Sprintf(
"%s\nError: Scan with --debug to view the details\n%s\n\n",
"%s\nError: Use configtest subcommand or scan with --debug to view the details\n%s\n\n",
header, r.Errors)
}
if len(r.Warnings) != 0 {
header += fmt.Sprintf(
"\nWarning: Some warnings occurred.\n%s\n\n",
r.Warnings)
}

if len(r.ScannedCves) == 0 {
return fmt.Sprintf(`
Expand Down Expand Up @@ -165,10 +186,16 @@ func formatFullPlainText(r models.ScanResult) (lines string) {
header := r.FormatTextReportHeadedr()
if len(r.Errors) != 0 {
return fmt.Sprintf(
"%s\nError: Scan with --debug to view the details\n%s\n\n",
"%s\nError: Use configtest subcommand or scan with --debug to view the details\n%s\n\n",
header, r.Errors)
}

if len(r.Warnings) != 0 {
header += fmt.Sprintf(
"\nWarning: Some warnings occurred.\n%s\n\n",
r.Warnings)
}

if len(r.ScannedCves) == 0 {
return fmt.Sprintf(`
%s
Expand Down
9 changes: 6 additions & 3 deletions scan/alpine.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,14 @@ func (o *alpine) scanPackages() error {

updatable, err := o.scanUpdatablePackages()
if err != nil {
o.log.Errorf("Failed to scan installed packages: %s", err)
return err
err = xerrors.Errorf("Failed to scan updatable packages: %w", err)
o.log.Warnf("err: %+v", err)
o.warns = append(o.warns, err)
// Only warning this error
} else {
installed.MergeNewVersion(updatable)
}

installed.MergeNewVersion(updatable)
o.Packages = installed
return nil
}
Expand Down
14 changes: 10 additions & 4 deletions scan/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,10 @@ type base struct {
osPackages
LibraryScanners []models.LibraryScanner
WordPress *models.WordPressPackages
log *logrus.Entry
errs []error

log *logrus.Entry
errs []error
warns []error
}

func (l *base) exec(cmd string, sudo bool) execResult {
Expand Down Expand Up @@ -403,9 +405,12 @@ func (l *base) convertToModel() models.ScanResult {
Tag: l.ServerInfo.Image.Tag,
}

errs := []string{}
errs, warns := []string{}, []string{}
for _, e := range l.errs {
errs = append(errs, fmt.Sprintf("%s", e))
errs = append(errs, fmt.Sprintf("%+v", e))
}
for _, w := range l.warns {
warns = append(warns, fmt.Sprintf("%+v", w))
}

scannedVia := scannedViaRemote
Expand Down Expand Up @@ -436,6 +441,7 @@ func (l *base) convertToModel() models.ScanResult {
LibraryScanners: l.LibraryScanners,
Optional: l.ServerInfo.Optional,
Errors: errs,
Warnings: warns,
}
}

Expand Down
12 changes: 9 additions & 3 deletions scan/debian.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,12 @@ func (o *debian) preCure() error {

func (o *debian) postScan() error {
if o.getServerInfo().Mode.IsDeep() || o.getServerInfo().Mode.IsFastRoot() {
return o.checkrestart()
if err := o.checkrestart(); err != nil {
err = xerrors.Errorf("Failed to scan need-restarting processes: %w", err)
o.log.Warnf("err: %+v", err)
o.warns = append(o.warns, err)
// Only warning this error
}
}
return nil
}
Expand All @@ -282,8 +287,9 @@ func (o *debian) scanPackages() error {
}
rebootRequired, err := o.rebootRequired()
if err != nil {
o.log.Errorf("Failed to detect the kernel reboot required: %s", err)
return err
o.log.Warnf("Failed to detect the kernel reboot required: %s", err)
o.warns = append(o.warns, err)
// Only warning this error
}
o.Kernel = models.Kernel{
Version: version,
Expand Down
9 changes: 5 additions & 4 deletions scan/freebsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,13 @@ func (o *bsd) scanPackages() error {
Version: version,
}

rebootRequired, err := o.rebootRequired()
o.Kernel.RebootRequired, err = o.rebootRequired()
if err != nil {
o.log.Errorf("Failed to detect the kernel reboot required: %s", err)
return err
err = xerrors.Errorf("Failed to detect the kernel reboot required: %w", err)
o.log.Warnf("err: %+v", err)
o.warns = append(o.warns, err)
// Only warning this error
}
o.Kernel.RebootRequired = rebootRequired

packs, err := o.scanInstalledPackages()
if err != nil {
Expand Down
Loading

0 comments on commit 17bb575

Please sign in to comment.