268 lines
9.6 KiB
YAML
268 lines
9.6 KiB
YAML
# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/api_fuzzing/
|
|
|
|
# Configure the scanning tool through the environment variables.
|
|
# List of the variables: https://docs.gitlab.com/ee/user/application_security/api_fuzzing/#available-variables
|
|
# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables
|
|
|
|
stages:
|
|
- build
|
|
- test
|
|
- deploy
|
|
- fuzz
|
|
|
|
variables:
|
|
FUZZAPI_PROFILE: Quick
|
|
FUZZAPI_VERSION: latest
|
|
FUZZAPI_CONFIG: .gitlab-api-fuzzing.yml
|
|
FUZZAPI_TIMEOUT: 30
|
|
FUZZAPI_REPORT: gl-api-fuzzing-report.json
|
|
FUZZAPI_REPORT_ASSET_PATH: assets
|
|
#
|
|
FUZZAPI_D_NETWORK: testing-net
|
|
#
|
|
# Wait up to 5 minutes for API Fuzzer and target url to become
|
|
# available (non 500 response to HTTP(s))
|
|
FUZZAPI_SERVICE_START_TIMEOUT: "300"
|
|
#
|
|
FUZZAPI_IMAGE: registry.gitlab.com/gitlab-org/security-products/analyzers/api-fuzzing:${FUZZAPI_VERSION}-engine
|
|
#
|
|
|
|
apifuzzer_fuzz_unlicensed:
|
|
stage: fuzz
|
|
allow_failure: true
|
|
rules:
|
|
- if: '$GITLAB_FEATURES !~ /\bapi_fuzzing\b/ && $API_FUZZING_DISABLED == null'
|
|
- when: never
|
|
script:
|
|
- |
|
|
echo "Error: Your GitLab project is not licensed for API Fuzzing."
|
|
- exit 1
|
|
|
|
apifuzzer_fuzz:
|
|
stage: fuzz
|
|
image:
|
|
name: $FUZZAPI_IMAGE
|
|
entrypoint: ["/bin/bash", "-l", "-c"]
|
|
variables:
|
|
FUZZAPI_PROJECT: $CI_PROJECT_PATH
|
|
FUZZAPI_API: http://apifuzzer:80
|
|
FUZZAPI_NEW_REPORT: 1
|
|
TZ: America/Los_Angeles
|
|
services:
|
|
- name: $FUZZAPI_IMAGE
|
|
alias: apifuzzer
|
|
entrypoint: ["dotnet", "/peach/Peach.Web.dll"]
|
|
allow_failure: true
|
|
rules:
|
|
- if: $FUZZAPI_D_TARGET_IMAGE
|
|
when: never
|
|
- if: $FUZZAPI_D_WORKER_IMAGE
|
|
when: never
|
|
- if: $API_FUZZING_DISABLED
|
|
when: never
|
|
- if: $API_FUZZING_DISABLED_FOR_DEFAULT_BRANCH &&
|
|
$CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
|
|
when: never
|
|
- if: $CI_COMMIT_BRANCH && $GITLAB_FEATURES =~ /\bapi_fuzzing\b/
|
|
script:
|
|
#
|
|
# Validate options
|
|
- |
|
|
if [ "$FUZZAPI_HAR$FUZZAPI_OPENAPI$FUZZAPI_POSTMAN_COLLECTION" == "" ]; then \
|
|
echo "Error: One of FUZZAPI_HAR, FUZZAPI_OPENAPI, or FUZZAPI_POSTMAN_COLLECTION must be provided."; \
|
|
echo "See https://docs.gitlab.com/ee/user/application_security/api_fuzzing/ for information on how to configure API Fuzzing."; \
|
|
exit 1; \
|
|
fi
|
|
#
|
|
# Run user provided pre-script
|
|
- sh -c "$FUZZAPI_PRE_SCRIPT"
|
|
#
|
|
# Make sure asset path exists
|
|
- mkdir -p $FUZZAPI_REPORT_ASSET_PATH
|
|
#
|
|
# Start scanning
|
|
- worker-entry
|
|
#
|
|
# Run user provided post-script
|
|
- sh -c "$FUZZAPI_POST_SCRIPT"
|
|
#
|
|
artifacts:
|
|
when: always
|
|
paths:
|
|
- $FUZZAPI_REPORT_ASSET_PATH
|
|
- $FUZZAPI_REPORT
|
|
reports:
|
|
api_fuzzing: $FUZZAPI_REPORT
|
|
|
|
apifuzzer_fuzz_dnd:
|
|
stage: fuzz
|
|
image: docker:19.03.12
|
|
variables:
|
|
DOCKER_DRIVER: overlay2
|
|
DOCKER_TLS_CERTDIR: ""
|
|
FUZZAPI_PROJECT: $CI_PROJECT_PATH
|
|
FUZZAPI_API: http://apifuzzer:80
|
|
allow_failure: true
|
|
rules:
|
|
- if: $FUZZAPI_D_TARGET_IMAGE == null && $FUZZAPI_D_WORKER_IMAGE == null
|
|
when: never
|
|
- if: $API_FUZZING_DISABLED
|
|
when: never
|
|
- if: $API_FUZZING_DISABLED_FOR_DEFAULT_BRANCH &&
|
|
$CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
|
|
when: never
|
|
- if: $CI_COMMIT_BRANCH && $GITLAB_FEATURES =~ /\bapi_fuzzing\b/
|
|
services:
|
|
- docker:19.03.12-dind
|
|
script:
|
|
#
|
|
#
|
|
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
|
|
#
|
|
- docker network create --driver bridge $FUZZAPI_D_NETWORK
|
|
#
|
|
# Run user provided pre-script
|
|
- sh -c "$FUZZAPI_PRE_SCRIPT"
|
|
#
|
|
# Make sure asset path exists
|
|
- mkdir -p $FUZZAPI_REPORT_ASSET_PATH
|
|
#
|
|
# Start peach testing engine container
|
|
- |
|
|
docker run -d \
|
|
--name apifuzzer \
|
|
--network $FUZZAPI_D_NETWORK \
|
|
-e Proxy:Port=8000 \
|
|
-e TZ=America/Los_Angeles \
|
|
-e GITLAB_FEATURES \
|
|
-p 80:80 \
|
|
-p 8000:8000 \
|
|
-p 514:514 \
|
|
--restart=no \
|
|
$FUZZAPI_IMAGE \
|
|
dotnet /peach/Peach.Web.dll
|
|
#
|
|
# Start target container
|
|
- |
|
|
if [ "$FUZZAPI_D_TARGET_IMAGE" != "" ]; then \
|
|
docker run -d \
|
|
--name target \
|
|
--network $FUZZAPI_D_NETWORK \
|
|
$FUZZAPI_D_TARGET_ENV \
|
|
$FUZZAPI_D_TARGET_PORTS \
|
|
$FUZZAPI_D_TARGET_VOLUME \
|
|
--restart=no \
|
|
$FUZZAPI_D_TARGET_IMAGE \
|
|
; fi
|
|
#
|
|
# Start worker container if provided
|
|
- |
|
|
if [ "$FUZZAPI_D_WORKER_IMAGE" != "" ]; then \
|
|
echo "Starting worker image $FUZZAPI_D_WORKER_IMAGE"; \
|
|
docker run \
|
|
--name worker \
|
|
--network $FUZZAPI_D_NETWORK \
|
|
-e FUZZAPI_API=http://apifuzzer:80 \
|
|
-e FUZZAPI_PROJECT \
|
|
-e FUZZAPI_PROFILE \
|
|
-e FUZZAPI_CONFIG \
|
|
-e FUZZAPI_REPORT \
|
|
-e FUZZAPI_REPORT_ASSET_PATH \
|
|
-e FUZZAPI_NEW_REPORT=1 \
|
|
-e FUZZAPI_HAR \
|
|
-e FUZZAPI_OPENAPI \
|
|
-e FUZZAPI_POSTMAN_COLLECTION \
|
|
-e FUZZAPI_TARGET_URL \
|
|
-e FUZZAPI_OVERRIDES_FILE \
|
|
-e FUZZAPI_OVERRIDES_ENV \
|
|
-e FUZZAPI_OVERRIDES_CMD \
|
|
-e FUZZAPI_OVERRIDES_INTERVAL \
|
|
-e FUZZAPI_TIMEOUT \
|
|
-e FUZZAPI_VERBOSE \
|
|
-e FUZZAPI_SERVICE_START_TIMEOUT \
|
|
-e FUZZAPI_HTTP_USERNAME \
|
|
-e FUZZAPI_HTTP_PASSWORD \
|
|
-e CI_PROJECT_URL \
|
|
-e CI_JOB_ID \
|
|
-e CI_COMMIT_BRANCH=${CI_COMMIT_BRANCH} \
|
|
$FUZZAPI_D_WORKER_ENV \
|
|
$FUZZAPI_D_WORKER_PORTS \
|
|
$FUZZAPI_D_WORKER_VOLUME \
|
|
--restart=no \
|
|
$FUZZAPI_D_WORKER_IMAGE \
|
|
; fi
|
|
#
|
|
# Start API Fuzzing provided worker if no other worker present
|
|
- |
|
|
if [ "$FUZZAPI_D_WORKER_IMAGE" == "" ]; then \
|
|
if [ "$FUZZAPI_HAR$FUZZAPI_OPENAPI$FUZZAPI_POSTMAN_COLLECTION" == "" ]; then \
|
|
echo "Error: One of FUZZAPI_HAR, FUZZAPI_OPENAPI, or FUZZAPI_POSTMAN_COLLECTION must be provided."; \
|
|
echo "See https://docs.gitlab.com/ee/user/application_security/api_fuzzing/ for information on how to configure API Fuzzing."; \
|
|
exit 1; \
|
|
fi; \
|
|
docker run \
|
|
--name worker \
|
|
--network $FUZZAPI_D_NETWORK \
|
|
-e TZ=America/Los_Angeles \
|
|
-e FUZZAPI_API=http://apifuzzer:80 \
|
|
-e FUZZAPI_PROJECT \
|
|
-e FUZZAPI_PROFILE \
|
|
-e FUZZAPI_CONFIG \
|
|
-e FUZZAPI_REPORT \
|
|
-e FUZZAPI_REPORT_ASSET_PATH \
|
|
-e FUZZAPI_NEW_REPORT=1 \
|
|
-e FUZZAPI_HAR \
|
|
-e FUZZAPI_OPENAPI \
|
|
-e FUZZAPI_POSTMAN_COLLECTION \
|
|
-e FUZZAPI_TARGET_URL \
|
|
-e FUZZAPI_OVERRIDES_FILE \
|
|
-e FUZZAPI_OVERRIDES_ENV \
|
|
-e FUZZAPI_OVERRIDES_CMD \
|
|
-e FUZZAPI_OVERRIDES_INTERVAL \
|
|
-e FUZZAPI_TIMEOUT \
|
|
-e FUZZAPI_VERBOSE \
|
|
-e FUZZAPI_SERVICE_START_TIMEOUT \
|
|
-e FUZZAPI_HTTP_USERNAME \
|
|
-e FUZZAPI_HTTP_PASSWORD \
|
|
-e CI_PROJECT_URL \
|
|
-e CI_JOB_ID \
|
|
-v $CI_PROJECT_DIR:/app \
|
|
-v `pwd`/$FUZZAPI_REPORT_ASSET_PATH:/app/$FUZZAPI_REPORT_ASSET_PATH:rw \
|
|
-p 81:80 \
|
|
-p 8001:8000 \
|
|
-p 515:514 \
|
|
--restart=no \
|
|
$FUZZAPI_IMAGE \
|
|
worker-entry \
|
|
; fi
|
|
#
|
|
# Propagate exit code from api fuzzing scanner (if any)
|
|
- if [[ $(docker inspect apifuzzer --format='{{.State.ExitCode}}') != "0" ]]; then echo "API Fuzzing scanner exited with an error. Logs are available as job artifacts."; exit 1; fi
|
|
#
|
|
# Run user provided post-script
|
|
- sh -c "$FUZZAPI_POST_SCRIPT"
|
|
#
|
|
after_script:
|
|
#
|
|
# Shutdown all containers
|
|
- echo "Stopping all containers"
|
|
- if [ "$FUZZAPI_D_TARGET_IMAGE" != "" ]; then docker stop target; fi
|
|
- docker stop worker
|
|
- docker stop apifuzzer
|
|
#
|
|
# Save docker logs
|
|
- docker logs apifuzzer &> gl-api_fuzzing-logs.log
|
|
- if [ "$FUZZAPI_D_TARGET_IMAGE" != "" ]; then docker logs target &> gl-api_fuzzing-target-logs.log; fi
|
|
- docker logs worker &> gl-api_fuzzing-worker-logs.log
|
|
#
|
|
artifacts:
|
|
when: always
|
|
paths:
|
|
- ./gl-api_fuzzing*.log
|
|
- ./gl-api_fuzzing*.zip
|
|
- $FUZZAPI_REPORT_ASSET_PATH
|
|
- $FUZZAPI_REPORT
|
|
reports:
|
|
api_fuzzing: $FUZZAPI_REPORT
|
|
|
|
# end
|