Skip to content

Commit

Permalink
Merge pull request #241 from lacework/afiune/fix
Browse files Browse the repository at this point in the history
fix(cli): generate html for scan commands
  • Loading branch information
afiune authored Nov 13, 2020
2 parents b884743 + fee8505 commit c18919a
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 45 deletions.
6 changes: 6 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ jobs:
- attach_workspace:
at: bin
- run: make integration-only
- store_artifacts:
path: circleci-artifacts
- slack/status:
fail_only: true
mentions: << pipeline.parameters.slack-mentions >>
Expand All @@ -73,6 +75,10 @@ jobs:
command: |
$env:LW_CLI_BIN = Join-Path (Get-Location).Path "bin\\lacework-cli-windows-amd64.exe"
go test -v github.com/lacework/go-sdk/integration
- slack/status:
fail_only: true
mentions: << pipeline.parameters.slack-mentions >>
only_for_branches: <<pipeline.parameters.only_for_branches>>
environment:
GOFLAGS: -mod=vendor
verify-release:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

# Go test coverage
coverage.out
circleci-artifacts/

# for building binary files
bin/
3 changes: 3 additions & 0 deletions cli/cmd/vuln_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,9 @@ func checkOnDemandContainerVulnerabilityStatus(reqID string) error {
}

cli.OutputHuman(buildVulnerabilityReport(results))
if vulCmdState.Html {
return generateVulnAssessmentHTML(results)
}
return nil
}

Expand Down
3 changes: 3 additions & 0 deletions cli/cmd/vulnerability.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,9 @@ func pollScanStatus(requestID string) error {

cli.StopProgress()
cli.OutputHuman(buildVulnerabilityReport(assessment))
if vulCmdState.Html {
return generateVulnAssessmentHTML(assessment)
}
return nil
}
}
Expand Down
65 changes: 57 additions & 8 deletions integration/container_vulnerability_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import (
"bytes"
"encoding/json"
"fmt"
"os"
"path"
"regexp"
"testing"

Expand All @@ -31,7 +33,8 @@ import (
const (
registry = "index.docker.io"
repository = "lacework/lacework-cli"
tag = "ubuntu-1804"
tag1 = "ubuntu-1804"
tag2 = "amazonlinux-2"
)

func TestContainerVulnerabilityCommandAliases(t *testing.T) {
Expand Down Expand Up @@ -84,19 +87,34 @@ func TestContainerVulnerabilityCommandListAssessments(t *testing.T) {
})
}

func TestContainerVulnerabilityCommandScanHumanReadable(t *testing.T) {
out, err, exitcode := LaceworkCLIWithTOMLConfig(
"vulnerability", "container", "scan", registry, repository, tag)
func TestContainerVulnerabilityCommandScanHumanReadablePollGenerateHtml(t *testing.T) {
// create a temporal directory to check that the HTML file is deployed
home := createTOMLConfigFromCIvars()
defer os.RemoveAll(home)
out, err, exitcode := LaceworkCLIWithHome(home,
"vulnerability", "container", "scan", registry, repository, tag2, "--poll", "--html")

assert.Contains(t, out.String(), "A new vulnerability scan has been requested. (request_id:",
"STDOUT changed, please check")
assert.Contains(t, out.String(), "lacework vulnerability container scan-status",
assert.Contains(t, out.String(), "The container vulnerability assessment was stored at 'lacework-lacework-cli-sha256",
"STDOUT changed, please check")
assert.Empty(t,
err.String(),
"STDERR should be empty")
assert.Equal(t, 0, exitcode,
"EXITCODE is not the expected one")

t.Run("assert that HTML file was generated", func(t *testing.T) {
var (
m = regexp.MustCompile(`sha256:([0-9a-z])+`)
shas = m.FindAllString(out.String(), -1)
imageDigest = shas[len(shas)-1]
)
assert.NotEmpty(t, imageDigest, "unable to extract image digest")
htmlFile := path.Join(home, fmt.Sprintf("lacework-lacework-cli-%s.html", imageDigest))
assert.FileExists(t, htmlFile, "the HTML file was not generated")
storeFileInCircleCI(htmlFile)
})
}

type containerVulnerabilityScan struct {
Expand All @@ -116,9 +134,9 @@ func TestContainerVulnerabilityCommandsEndToEnd(t *testing.T) {
// "requestId": "e94f2774-5662-4510-8ebf-2d5e3cd317f6",
// "status": "Scanning"
// }
t.Run(fmt.Sprintf("run scan for %s/%s:%s", registry, repository, tag), func(t *testing.T) {
t.Run(fmt.Sprintf("run scan for %s/%s:%s", registry, repository, tag1), func(t *testing.T) {
out, err, exitcode = LaceworkCLIWithTOMLConfig(
"vulnerability", "container", "scan", registry, repository, tag, "--json")
"vulnerability", "container", "scan", registry, repository, tag1, "--json")
assert.Empty(t,
err.String(),
"STDERR should be empty")
Expand Down Expand Up @@ -172,7 +190,7 @@ func TestContainerVulnerabilityCommandsEndToEnd(t *testing.T) {
// fields
"Registry " + registry,
"Repository " + repository,
"Tags " + tag,
"Tags " + tag1,
"Size",
"ID",
"Digest",
Expand Down Expand Up @@ -210,4 +228,35 @@ func TestContainerVulnerabilityCommandsEndToEnd(t *testing.T) {
assert.Contains(t, scanStatusOutput, showAssessmentOutput,
"STDOUT from scan-status and show-assessment are not the same")
})

// render an HTML file using the show-assessment command
t.Run("render HTML file using show-assessment command", func(t *testing.T) {
// create a temporal directory to check that the HTML file is deployed
home := createTOMLConfigFromCIvars()
defer os.RemoveAll(home)
out, err, exitcode = LaceworkCLIWithHome(home,
"vulnerability", "container", "show-assessment", imageID, "--image_id", "--html")
assert.Empty(t,
err.String(),
"STDERR should be empty")
assert.Equal(t, 0, exitcode,
"EXITCODE is not the expected one")
assert.Contains(t, out.String(), "The container vulnerability assessment was stored at 'lacework-lacework-cli-sha256",
"STDOUT changed, please check")

assert.NotContains(t, out.String(), "Try adding '--details' to increase details shown about the vulnerability assessment.",
"STDOUT breadcrumbs should not be displayed")

t.Run("assert that HTML file was generated", func(t *testing.T) {
var (
m = regexp.MustCompile(`sha256:([0-9a-z])+`)
shas = m.FindAllString(out.String(), -1)
imageDigest = shas[len(shas)-1]
)
assert.NotEmpty(t, imageDigest, "unable to extract image digest")
htmlFile := path.Join(home, fmt.Sprintf("lacework-lacework-cli-%s.html", imageDigest))
assert.FileExists(t, htmlFile, "the HTML file was not generated")
storeFileInCircleCI(htmlFile)
})
})
}
20 changes: 20 additions & 0 deletions integration/framework_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"log"
"os"
"os/exec"
"path"
"path/filepath"
"runtime"
)
Expand Down Expand Up @@ -194,3 +195,22 @@ api_secret = '_11111111111111111111111111111111'
}
return dir
}

// store a file in Circle CI Working directory, only if we are running on CircleCI
func storeFileInCircleCI(f string) {
if jobDir := os.Getenv("CIRCLE_WORKING_DIRECTORY"); jobDir != "" {
var (
file = filepath.Base(f)
artifacts = path.Join(jobDir, "circleci-artifacts")
err = os.Mkdir(artifacts, 0755)
)
if err != nil {
fmt.Println(err)
}

err = os.Rename(f, path.Join(artifacts, file))
if err != nil {
fmt.Println(err)
}
}
}
101 changes: 64 additions & 37 deletions scripts/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ readonly org_name=lacework
readonly package_name=lacework-cli
readonly binary_name=lacework
readonly docker_org=lacework
readonly git_user="Salim Afiune Maya"
readonly git_email="[email protected]"
readonly docker_tags=(
latest
scratch
Expand Down Expand Up @@ -80,25 +82,16 @@ main() {
}

trigger_release() {
if [[ "$VERSION" =~ "-release" ]]; then
log "VERSION has 'x.y.z-release' tag. Triggering a release!"
log ""
log "removing release tag from version '${VERSION}'"
remove_tag_version
log "commiting and pushing the version bump to github"
git config --global user.email "[email protected]"
git config --global user.name "Salim Afiune Maya"
git add VERSION
git add api/version.go # file genereted by scripts/version_updater.sh
git commit -m "trigger release v$VERSION"
git push origin master
tag_release
bump_version
else
if [[ "$VERSION" =~ "-dev" ]]; then
log "No release needed. (VERSION=${VERSION})"
log ""
log "Read more about the release process at:"
log " - https://github.com/${org_name}/${project_name}/wiki/Release-Process"
else
log "VERSION ready to be released to 'x.y.z' tag. Triggering a release!"
log ""
tag_release
bump_version
fi
}

Expand All @@ -123,14 +116,14 @@ verify_release() {
fi
done

if [[ "$VERSION" =~ "-release" ]]; then
log "(required) VERSION has 'x.y.z-release' tag. Great!"
else
warn "the 'VERSION' needs to be updated to have the 'x.y.z-release' tag"
if [[ "$VERSION" =~ "-dev" ]]; then
warn "the 'VERSION' needs to be cleaned up to be only 'x.y.z' tag"
warn ""
warn "Read more about the release process at:"
warn " - https://github.com/${org_name}/${project_name}/wiki/Release-Process"
exit 123
else
log "(required) VERSION has been cleaned up to 'x.y.z' tag. Great!"
fi
}

Expand All @@ -141,7 +134,6 @@ prepare_release() {
cli_generate_files
generate_release_notes
update_changelog
add_tag_version "release"
push_release
}

Expand Down Expand Up @@ -174,23 +166,56 @@ update_changelog() {
load_list_of_changes() {
latest_version=$(find_latest_version)
local _list_of_changes=$(git log --no-merges --pretty="* %s (%an)([%h](https://github.com/${org_name}/${project_name}/commit/%H))" ${latest_version}..master)
echo "## Features" > CHANGES.md
echo "$_list_of_changes" | grep "\* feat[:(]" >> CHANGES.md
echo "## Refactor" >> CHANGES.md
echo "$_list_of_changes" | grep "\* refactor[:(]" >> CHANGES.md
echo "## Performance Improvements" >> CHANGES.md
echo "$_list_of_changes" | grep "\* perf[:(]" >> CHANGES.md
echo "## Bug Fixes" >> CHANGES.md
echo "$_list_of_changes" | grep "\* fix[:(]" >> CHANGES.md
echo "## Documentation Updates" >> CHANGES.md
echo "$_list_of_changes" | grep "\* doc[:(]" >> CHANGES.md
echo "$_list_of_changes" | grep "\* docs[:(]" >> CHANGES.md
echo "## Other Changes" >> CHANGES.md
echo "$_list_of_changes" | grep "\* style[:(]" >> CHANGES.md
echo "$_list_of_changes" | grep "\* chore[:(]" >> CHANGES.md
echo "$_list_of_changes" | grep "\* build[:(]" >> CHANGES.md
echo "$_list_of_changes" | grep "\* ci[:(]" >> CHANGES.md
echo "$_list_of_changes" | grep "\* test[:(]" >> CHANGES.md

# init changes file
true > CHANGES.md

_feat=$(echo "$_list_of_changes" | grep "\* feat[:(]")
_refactor=$(echo "$_list_of_changes" | grep "\* refactor[:(]")
_perf=$(echo "$_list_of_changes" | grep "\* perf[:(]")
_fix=$(echo "$_list_of_changes" | grep "\* fix[:(]")
_doc=$(echo "$_list_of_changes" | grep "\* doc[:(]")
_docs=$(echo "$_list_of_changes" | grep "\* docs[:(]")
_style=$(echo "$_list_of_changes" | grep "\* style[:(]")
_chore=$(echo "$_list_of_changes" | grep "\* chore[:(]")
_build=$(echo "$_list_of_changes" | grep "\* build[:(]")
_ci=$(echo "$_list_of_changes" | grep "\* ci[:(]")
_test=$(echo "$_list_of_changes" | grep "\* test[:(]")

if [ "$_feat" != "" ]; then
echo "## Features" >> CHANGES.md
echo "$_feat" >> CHANGES.md
fi

if [ "$_refactor" != "" ]; then
echo "## Refactor" >> CHANGES.md
echo "$_refactor" >> CHANGES.md
fi

if [ "$_perf" != "" ]; then
echo "## Performance Improvements" >> CHANGES.md
echo "$_perf" >> CHANGES.md
fi

if [ "$_fix" != "" ]; then
echo "## Bug Fixes" >> CHANGES.md
echo "$_fix" >> CHANGES.md
fi

if [ "${_docs}${_doc}" != "" ]; then
echo "## Documentation Updates" >> CHANGES.md
if [ "$_doc" != "" ]; then echo "$_doc" >> CHANGES.md; fi
if [ "$_docs" != "" ]; then echo "$_docs" >> CHANGES.md; fi
fi

if [ "${_style}${_chore}${_build}${_ci}${_test}" != "" ]; then
echo "## Other Changes" >> CHANGES.md
if [ "$_style" != "" ]; then echo "$_style" >> CHANGES.md; fi
if [ "$_chore" != "" ]; then echo "$_chore" >> CHANGES.md; fi
if [ "$_build" != "" ]; then echo "$_build" >> CHANGES.md; fi
if [ "$_ci" != "" ]; then echo "$_ci" >> CHANGES.md; fi
if [ "$_test" != "" ]; then echo "$_test" >> CHANGES.md; fi
fi
}

generate_release_notes() {
Expand Down Expand Up @@ -297,6 +322,8 @@ bump_version() {
fi

log "commiting and pushing the vertion bump to github"
git config --global user.email $git_email
git config --global user.name $git_user
git add VERSION
git add api/version.go # file genereted by scripts/version_updater.sh
git commit -m "version bump to v$VERSION"
Expand Down

0 comments on commit c18919a

Please sign in to comment.