Skip to content

Commit

Permalink
feat(ux): improve container scan error messages
Browse files Browse the repository at this point in the history
JIRA ALLY-402

Signed-off-by: Salim Afiune Maya <[email protected]>
  • Loading branch information
afiune committed Mar 23, 2021
1 parent 7a828fe commit 34e6ee7
Show file tree
Hide file tree
Showing 9 changed files with 183 additions and 33 deletions.
4 changes: 2 additions & 2 deletions api/integrations_ctr_reg.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ func (svc *IntegrationsService) UpdateContainerRegistry(integration ContainerReg
return
}

// ListContainerRegistries lists the CONT_VULN_CFG external integrations available on the Lacework Server
func (svc *IntegrationsService) ListContainerRegistries() (response ContainerRegIntResponse, err error) {
// ListContainerRegistryIntegrations lists the CONT_VULN_CFG external integrations available on the Lacework Server
func (svc *IntegrationsService) ListContainerRegistryIntegrations() (response ContainerRegIntResponse, err error) {
err = svc.listByType(ContainerRegistryIntegration, &response)
return
}
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/compliance.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Get started by integrating one or more cloud accounts using the command:
$ lacework integration create
Or, if you prefer to do it via the WebUI, log in to your account at:
If you prefer to configure the integration via the WebUI, log in to your account at:
https://<ACCOUNT>.lacework.net
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/compliance_aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Get started by integrating your AWS accounts to analyze configuration compliance
$ lacework integration create
Or, if you prefer to do it via the WebUI, log in to your account at:
If you prefer to configure the integration via the WebUI, log in to your account at:
https://%s.lacework.net
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/compliance_azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ Get started by integrating your Azure Tenants to analyze configuration complianc
$ lacework integration create
Or, if you prefer to do it via the WebUI, log in to your account at:
If you prefer to configure the integration via the WebUI, log in to your account at:
https://%s.lacework.net
Expand Down
123 changes: 97 additions & 26 deletions cli/cmd/vuln_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ Arguments:
<repository> repository name that contains the container image
<tag|digest> either a tag or an image digest to scan (digest format: sha256:1ee...1d3b)
To list all Container Registries configured in your account:
To list all container registries configured in your account:
$ lacework vuln container list-registries`,
$ lacework vulnerability container list-registries`,
Args: cobra.ExactArgs(3),
RunE: func(_ *cobra.Command, args []string) error {
return requestOnDemandContainerVulnerabilityScan(args)
Expand All @@ -75,22 +75,22 @@ To list all Container Registries configured in your account:
vulContainerListRegistriesCmd = &cobra.Command{
Use: "list-registries",
Aliases: []string{"list-reg", "registries"},
Short: "list all Container Registries configured",
Long: `List all Container Registries configured in your account.`,
Short: "list all container registries configured",
Long: `List all container registries configured in your account.`,
Args: cobra.NoArgs,
RunE: func(_ *cobra.Command, args []string) error {
regsIntegrations, err := cli.LwApi.Integrations.ListContainerRegistries()
registries, err := getContainerRegistries()
if err != nil {
return errors.Wrap(err, "unable to get container registry integrations")
return err
}
if len(regsIntegrations.Data) == 0 {
msg := `There are no Container Registries configured in your account.
if len(registries) == 0 {
msg := `There are no container registries configured in your account.
Get started by integrating your Container Registry using the command:
Get started by integrating your container registry using the command:
$ lacework integration create
Or, if you prefer to do it via the WebUI, log in to your account at:
If you prefer to configure the integration via the WebUI, log in to your account at:
https://%s.lacework.net
Expand All @@ -100,21 +100,6 @@ Then navigate to Settings > Integrations > Container Registry.
return nil
}

registries := make([]string, 0)
for _, i := range regsIntegrations.Data {
// avoid adding empty registries coming from the new local_scanner
if i.Data.RegistryDomain == "" {
continue
}

// avoid adding duplicate registries
if array.ContainsStr(registries, i.Data.RegistryDomain) {
continue
}

registries = append(registries, i.Data.RegistryDomain)
}

if cli.JSONOutput() {
return cli.OutputJSON(registries)
}
Expand Down Expand Up @@ -340,7 +325,7 @@ func requestOnDemandContainerVulnerabilityScan(args []string) error {
)
scan, err := cli.LwApi.Vulnerabilities.Container.Scan(args[0], args[1], args[2])
if err != nil {
return errors.Wrap(err, "unable to request on-demand vulnerability scan")
return userFriendlyErrorForOnDemandCtrVulnScan(err, args[0], args[1], args[2])
}

cli.Log.Debugw("vulnerability scan", "details", scan)
Expand Down Expand Up @@ -819,3 +804,89 @@ func filterSeverity(severity string, threshold string) bool {
func vulFiltersEnabled() bool {
return vulCmdState.Severity != "" || vulCmdState.Fixable
}

func getContainerRegistries() ([]string, error) {
var (
registries = make([]string, 0)
regsIntegrations, err = cli.LwApi.Integrations.ListContainerRegistryIntegrations()
)
if err != nil {
return registries, errors.Wrap(err, "unable to get container registry integrations")
}

for _, i := range regsIntegrations.Data {
// avoid adding empty registries coming from the new local_scanner and avoid adding duplicate registries
if i.Data.RegistryDomain == "" || array.ContainsStr(registries, i.Data.RegistryDomain) {
continue
}

registries = append(registries, i.Data.RegistryDomain)
}

return registries, nil
}

// Creates a user-friendly error message
func userFriendlyErrorForOnDemandCtrVulnScan(err error, registry, repo, tag string) error {
if strings.Contains(err.Error(),
"Could not find integraion matching the registry provided",
) || strings.Contains(err.Error(),
"Could not find vulnerability integrations",
) {

registries, errReg := getContainerRegistries()
if errReg != nil {
cli.Log.Debugw("error trying to retrieve configured registries", "error", errReg)
return errors.Errorf("container registry '%s' not found", registry)
}

if len(registries) == 0 {
msg := `there are no container registries configured in your account.
Get started by integrating your container registry using the command:
$ lacework integration create
If you prefer to configure the integration via the WebUI, log in to your account at:
https://%s.lacework.net
Then navigate to Settings > Integrations > Container Registry.
`
return errors.New(fmt.Sprintf(msg, cli.Account))
}

msg := `container registry '%s' not found
Your account has the following container registries configured:
> %s
To integrate a new container registry use the command:
$ lacework integration create
`
return errors.New(fmt.Sprintf(msg, registry, strings.Join(registries, "\n > ")))
}

if strings.Contains(
err.Error(),
"Could not successfully send scan request to available integrations for given repo and label",
) {

msg := `container image '%s:%s' not found in registry '%s'.
This error is likely due to a problem with the container registry integration
configured in your account. Verify that the integration was configured with
Lacework using the correct permissions, and that the repository belongs
to the provided registry.
To view all container registries configured in your account use the command:
$ lacework vulnerability container list-registries
`
return errors.Errorf(msg, repo, tag, registry)
}

return errors.Wrap(err, "unable to request on-demand vulnerability scan")
}
44 changes: 44 additions & 0 deletions cli/cmd/vuln_container_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// Author:: Salim Afiune Maya (<[email protected]>)
// Copyright:: Copyright 2021, Lacework Inc.
// License:: Apache License, Version 2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package cmd

import (
"testing"

"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)

func TestUserFriendlyErrorFromOnDemandCtrVulnScanRepositoryNotFound(t *testing.T) {
err := userFriendlyErrorForOnDemandCtrVulnScan(
errors.New("Could not successfully send scan request to available integrations for given repo and label"),
"my-registry.example.com", "image", "tag",
)
if assert.NotNil(t, err) {
assert.Contains(t,
err.Error(),
"container image 'image:tag' not found in registry 'my-registry.example.com'")
assert.Contains(t,
err.Error(),
"To view all container registries configured in your account use the command:")
assert.Contains(t,
err.Error(),
"$ lacework vulnerability container list-registries")
}
}
2 changes: 1 addition & 1 deletion cli/cmd/vulnerability.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ To create a new integration use the following command:
$ lacework integration create
Or, if you prefer to do it via the WebUI, log in to your account at:
If you prefer to configure the integration via the WebUI, log in to your account at:
https://<ACCOUNT>.lacework.net
Expand Down
2 changes: 1 addition & 1 deletion integration/compliance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Get started by integrating one or more cloud accounts using the command:
$ lacework integration create
Or, if you prefer to do it via the WebUI, log in to your account at:
If you prefer to configure the integration via the WebUI, log in to your account at:
https://<ACCOUNT>.lacework.net
Expand Down
35 changes: 35 additions & 0 deletions integration/container_vulnerability_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,41 @@ func TestContainerVulnerabilityCommandListAssessments(t *testing.T) {
})
}

func TestContainerVulnerabilityCommandScanErrorRegistryNotFound(t *testing.T) {
out, err, exitcode := LaceworkCLIWithTOMLConfig(
"vulnerability", "container", "scan", "my.registry.example.com", "foo", "bar",
)
assert.Empty(t, out.String(),
"STDOUT should be empty")
assert.Contains(t, err.String(),
"container registry 'my.registry.example.com' not found",
"STDERR mismatch, please check")
assert.Contains(t, err.String(),
"Your account has the following container registries configured",
"STDERR mismatch, please check")
assert.Contains(t, err.String(),
fmt.Sprintf("> %s", registry),
"STDERR mismatch, please check")
assert.Equal(t, 1, exitcode,
"EXITCODE is not the expected one")
}

func TestContainerVulnerabilityCommandScanErrorContainerImageNotFound(t *testing.T) {
out, err, exitcode := LaceworkCLIWithTOMLConfig(
"vulnerability", "container", "scan", registry, "foo", "bar",
)
assert.Empty(t, out.String(),
"STDOUT should be empty")
assert.Contains(t, err.String(),
fmt.Sprintf("container image 'foo:bar' not found in registry '%s'.", registry),
"STDERR mismatch, please check")
assert.Contains(t, err.String(),
"To view all container registries configured in your account use the command",
"STDERR mismatch, please check")
assert.Equal(t, 1, exitcode,
"EXITCODE is not the expected one")
}

func TestContainerVulnerabilityCommandScanHumanReadablePollGenerateHtml(t *testing.T) {
// create a temporal directory to check that the HTML file is deployed
home := createTOMLConfigFromCIvars()
Expand Down

0 comments on commit 34e6ee7

Please sign in to comment.