The scenario is:
- Vulnerability scanning with NeuVector as part of a AWS CodeBuild phase
- Sending the scan result report back to a NeuVector controller
- Pushing the image to a registry if no high severity vulnerabilities were found
The two key elements are, scanning local before pushing to a registry, sending the scan report to NeuVector for further processing and reporting.
This repository contains example code which was covered in a Blog and demonstrated in the talks:
- SUSECON 24: [TUTORIAL-1156] NeuVector Integration into AWS CodePipeline CI/CD Workflow
- openSUSE Conference 24: NeuVector Integration into AWS CodePipeline CI/CD workflow
The repository contains a sample buildspec.yaml to configure AWS CodeBuild and a scan.sh script to perform the NeuVector scan operation.
Actions performed inside AWS CodeBuild phases.
install
- Generate 8 digit git commit hash
- Retrieve ECR credentials and login to registry
- Make
scan.shexecutable
pre-build
- Start local docker registry (see Digest/RepoDigest value Workaround)
build
- local docker image build and tagging
- push to local registry
- perform NeuVector scan
post-build
- If
buildphase was successful, push image to ECR withlatestand<commit_hash>as label.
To apply the shared information, an understanding of AWS CodeBuild and it's terminology is expected.
We make assumptions that the surrounding infrastructure is already created and in a working state.
This includes:
- A CI/CD pipeline setup, for example AWS CodePipeline.
- A running NeuVector installation with an exposed controller API that is reachable inside your VPC.
- CodeBuild configured to connect for VPC connectivity.
- A user in NeuVector with the necessary permissions to upload a scan report
- The user password is saved in AWS Secrets Manager. If this is not the case, then the example
buildspec.yamlhas to be adjusted accordingly. - A second input source called
buildscriptsthat contains thescan.shscript. You can of course refactor this part in thebuildspec.yamland adjust it based on your needs. - Setting the AWS CodeBuild Environment to Privileged, this is required by the NeuVector standalone scanner to run.
If you are not interested in puhsing the scan results to NeuVector, then you don't need a NeuVector installation.
The buildspec.yaml file requires that multiple environment variables are set based on your individual setup.
NV_USERNAME= User that uploads the scan results to NeuVectorNV_CONTROLLER= NeuVector Controller API IP or URL that is used to upload the scan resultsOCIREPO= Name of the image repositoryOCIREPOURI= URL of the image repositoryOCINAME= Name of the application / image. Mainly used for the local scan and as name when uploading to NeuVectorNV_PASSWORD= Password to authenticate against the NeuVector API. Recommend to create it in AWS Secrets Manager. If you decide to add the password in cleartext to yourbuildspec.yaml(not recommended), then please remove the linesecrets-manager:and addNV_PASSWORDincluding it's value to the regular environment variables.
Please see Build specification reference for CodeBuild for general questions about the syntax and functionality of the buildspec.yaml file.
A standalone scan will create a scan_results.json file. This file is parsed in scan.sh by using jq to get the count of found high, medium and low severity vulnerabilities. Also to decide if a scan has failed, defined by high severity vulnerability count greater than 0.
To submit the report to a NeuVector Controller, three environment variables need to be passed to the neuvector/scanner container:
-e SCANNER_CTRL_API_USERNAME=<value> \
-e SCANNER_CTRL_API_PASSWORD=<value> \
-e CLUSTER_JOIN_ADDR=<value> \
SCANNER_CTRL_API_USERNAME and SCANNER_CTRL_API_PASSWORD are mentioned in the NeuVector release notes. CLUSTER_JOIN_ADDR is explained in NeuVector Documentation - Standalone scanner for local scanning.
Those variables are set via NV_USERNAME, NV_PASSWORD and NV_CONTROLLER in the example buildspec.yaml file and passed to neuvector/scanner in scan.sh.
If you are only interested in a standalone scan with fail or pass as outcome, don't pass the variables to the scanner.
When they are not set, then the results will not uploaded and the scanning works without a connection to a NeuVector installation.
NeuVector controller expects that a scan result that is submitted contains a value for Digest or RepoDigest.
Otherwise the upload fails with error ERRO|SCN|main.main: Failed to sumit scan result - error=Submit scan result failed with status code 400.
When an image is build locally inside AWS CodeBuild via docker, then this value is missing.
This is per design and how docker works in general. The value is generated and set as soon an image is pushed to a registry.
Build phase scanning of local images is considered a valid use-case of NeuVector.
Digest or RepoDigest should therefore not mandatory to submit scan results.
The issue is reported in the NeuVector upstream project: neuvector/neuvector#1423
In the pre_build phase of this example, a local registry is started by running the command docker run -d -p 5000:5000 --name registry registry:2.
docker build adds an additional tag for this local registry. After a successful build, the image is pushed.
This generates the required value, but the image doesn't leave the CodeBuild environment at this point.
It satisfies the requirement from NeuVector to receive a Digest value when submitting scan_results.json.
See CONTRIBUTING for more information.
This library is licensed under the MIT-0 License. See the LICENSE file.