.gitlab-ci.yml
# Jobs defined here use the idp/ci docker image from ECR by default. To find
# other available images:
# aws ecr describe-repositories | jq '.repositories[].repositoryUri'
# Images are built via the identity-devops GitLab pipeline.
variables:
ECR_REGISTRY: '${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com'
IDP_WORKER_IMAGE_TAG: 'main'
IDP_IMAGE_TAG: 'main'
PKI_IMAGE_TAG: 'main'
DASHBOARD_CI_SHA: 'sha256:b95a19d9b71d12604982572bad611cec59e87153c325cd54892ea82c13f70d8b'
GITLAB_CI: 'true'
default:
image: '${ECR_REGISTRY}/dashboard/ci:latest'
.bundle_install: &bundle_install
- bundle check || bundle install --deployment --jobs=4 --retry=3 --without deploy development doc production --path vendor/ruby
.yarn_install: &yarn_install
- yarn install --frozen-lockfile --ignore-engines --cache-folder .yarn-cache
.yarn_production_install: &yarn_production_install
- yarn install --production --frozen-lockfile --ignore-engines --cache-folder .yarn-cache
.build_cache:
- &ruby_cache
key:
files:
- Gemfile.lock
paths:
- vendor/ruby
policy: pull
- &yarn_cache
key:
files:
- yarn.lock
paths:
- .yarn-cache/
policy: pull
- &yarn_production_cache
key:
files:
- yarn.lock
paths:
- .yarn-cache/
policy: pull
- &assets_cache
key: $CI_COMMIT_SHA
paths:
- tmp/cache/assets
- public/assets
- public/packs
policy: pull
stages:
- build
- test
- review
- scan
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
when: never
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" || $CI_PIPELINE_SOURCE == "external_pull_request_event"'
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" || $CI_PIPELINE_SOURCE == "external_pull_request_event" || $CI_PIPELINE_SOURCE == "web"'
- if: '$CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "stages/prod"'
- if: '$CI_MERGE_REQUEST_IID || $CI_EXTERNAL_PULL_REQUEST_IID'
install:
stage: build
variables:
RAILS_ENV: test
SKIP_YARN_INSTALL: 'true'
cache:
- <<: *ruby_cache
policy: pull-push
- <<: *yarn_cache
policy: pull-push
- <<: *assets_cache
policy: push
script:
- *bundle_install
- *yarn_install
- bundle exec rake assets:precompile
# Build a container image async, and don't block CI tests
# Cache intermediate images for 1 week (168 hours)
build-review-image:
stage: review
needs: []
interruptible: true
variables:
BRANCH_TAGGING_STRING: ''
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
variables:
BRANCH_TAGGING_STRING: "--destination ${ECR_REGISTRY}/identity-dashboard/review:main"
- if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
- if: $CI_PIPELINE_SOURCE != "merge_request_event"
when: never
tags:
- build-pool
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: ['']
script:
- mkdir -p /kaniko/.docker
- |-
KANIKOCFG="\"credsStore\":\"ecr-login\""
if [ "x${http_proxy}" != "x" -o "x${https_proxy}" != "x" ]; then
KANIKOCFG="${KANIKOCFG}, \"proxies\": { \"default\": { \"httpProxy\": \"${http_proxy}\", \"httpsProxy\": \"${https_proxy}\", \"noProxy\": \"${no_proxy}\"}}"
fi
KANIKOCFG="{ ${KANIKOCFG} }"
echo "${KANIKOCFG}" > /kaniko/.docker/config.json
- >-
/kaniko/executor
--context "${CI_PROJECT_DIR}"
--dockerfile "${CI_PROJECT_DIR}/dockerfiles/dashboard_review_app.Dockerfile"
--destination "${ECR_REGISTRY}/identity-dashboard/review:${CI_COMMIT_SHA}"
${BRANCH_TAGGING_STRING}
--cache-repo="${ECR_REGISTRY}/identity-dashboard/review/cache"
--cache-ttl=168h
--cache=true
--compressed-caching=false
--build-arg "http_proxy=${http_proxy}" --build-arg "https_proxy=${https_proxy}" --build-arg "no_proxy=${no_proxy}"
build-ci-image:
stage: build
interruptible: true
needs: []
tags:
- build-pool
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: ['']
rules:
# Build when there are changes to the Dockerfile
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_PIPELINE_SOURCE == "web"'
changes:
compare_to: 'refs/heads/main'
paths:
- dockerfiles/dashboard_ci.Dockerfile
script:
- mkdir -p /kaniko/.docker
- |-
KANIKOCFG="\"credsStore\":\"ecr-login\""
if [ "x${http_proxy}" != "x" -o "x${https_proxy}" != "x" ]; then
KANIKOCFG="${KANIKOCFG}, \"proxies\": { \"default\": { \"httpProxy\": \"${http_proxy}\", \"httpsProxy\": \"${https_proxy}\", \"noProxy\": \"${no_proxy}\"}}"
fi
KANIKOCFG="{ ${KANIKOCFG} }"
echo "${KANIKOCFG}" > /kaniko/.docker/config.json
- >-
/kaniko/executor
--context "${CI_PROJECT_DIR}"
--dockerfile "${CI_PROJECT_DIR}/dockerfiles/dashboard_ci.Dockerfile"
--destination "${ECR_REGISTRY}/dashboard/ci:latest"
--destination "${ECR_REGISTRY}/dashboard/ci:${CI_COMMIT_SHA}"
--build-arg "http_proxy=${http_proxy}" --build-arg "https_proxy=${https_proxy}" --build-arg "no_proxy=${no_proxy}"
lint:
stage: test
needs:
- job: install
cache:
- <<: *ruby_cache
- <<: *yarn_cache
- <<: *assets_cache
variables:
JUNIT_OUTPUT: 'true'
script:
- *bundle_install
- *yarn_install
- make lint
artifacts:
expire_in: 31d
when: always
paths:
- rubocop.xml
reports:
junit: rubocop.xml
specs:
stage: test
needs:
- job: install
cache:
- <<: *ruby_cache
- <<: *yarn_cache
- <<: *assets_cache
variables:
AWS_ACCESS_KEY_ID: test
AWS_DEFAULT_REGION: us-west-2
AWS_REGION: us-west-2
AWS_SECRET_ACCESS_KEY: test
CAPYBARA_WAIT_TIME_SECONDS: 5
COVERAGE: 'true'
COBERTURA_FORMATTER_ENABLED: 'true'
DOCKER_DB_HOST: db-postgres
POSTGRES_DB: identity-dashboard_test
POSTGRES_USER: postgres_user
POSTGRES_PASSWORD: postgres_password
POSTGRES_HOST_AUTH_METHOD: trust
RAILS_ENV: test
services:
- name: postgres:13.9
alias: db-postgres
command: ['--fsync=false', '--synchronous_commit=false', '--full_page_writes=false']
script:
- mkdir coverage
- *bundle_install
- *yarn_install
- cp config/application.yml.default config/application.yml
- bundle exec rake db:setup
- bundle exec rspec --format documentation --format RspecJunitFormatter --out rspec.xml
coverage: '/\(\d+.\d+\%\) covered/'
artifacts:
when: always
reports:
junit: rspec.xml
coverage_report:
coverage_format: cobertura
path: coverage/coverage.xml
expire_in: 31d
paths:
- coverage/coverage.xml
- rspec.xml
review-app:
stage: review
allow_failure: true
needs:
- job: build-review-image
resource_group: $CI_ENVIRONMENT_SLUG-dashboard.reviewapp.identitysandbox.gov
image:
name: dtzar/helm-kubectl:latest
script:
- kubectl config get-contexts
- export CONTEXT=$(kubectl config get-contexts | grep reviewapp | awk '{print $1}' | head -1)
- kubectl config use-context "$CONTEXT"
- |-
export IDP_CONFIG=$(cat <<EOF
{
"kubernetesReviewApp": "true",
"postgres": {
"sslmode": "prefer",
"name": "idp",
"host": "$CI_ENVIRONMENT_SLUG-login-chart-pg.review-apps"
},
"postgresWorker": {
"sslmode": "prefer",
"name": "idp",
"host": "$CI_ENVIRONMENT_SLUG-login-chart-pg.review-apps"
},
"railsOffline": "true",
"redis": {
"irsAttemptsApiUrl": "redis://$CI_ENVIRONMENT_SLUG-login-chart-redis.review-apps:6379/2",
"throttleUrl": "redis://$CI_ENVIRONMENT_SLUG-login-chart-redis.review-apps:6379/1",
"url": "redis://$CI_ENVIRONMENT_SLUG-login-chart-redis.review-apps:6379"
},
"assetHost": "https://$CI_ENVIRONMENT_SLUG.reviewapp.identitysandbox.gov",
"domainName": "$CI_ENVIRONMENT_SLUG.reviewapp.identitysandbox.gov",
"loginDatacenter": "true",
"loginDomain": "identitysandbox.gov",
"loginEnv": "$CI_ENVIRONMENT_SLUG",
"loginHostRole": "idp",
"loginSkipRemoteConfig": "true",
"pivcacServiceUrl": "https://$CI_ENVIRONMENT_SLUG.pivcac.reviewapp.identitysandbox.gov/",
"pivcacVerifyTokenUrl": "https://$CI_ENVIRONMENT_SLUG.pivcac.reviewapp.identitysandbox.gov/",
"dashboardUrl": "https://$CI_ENVIRONMENT_SLUG-dashboard.reviewapp.identitysandbox.gov"
}
EOF
)
- |-
export WORKER_CONFIG=$(cat <<EOF
{
"kubernetesReviewApp": "true",
"postgres": {
"sslmode": "prefer",
"name": "idp",
"host": "$CI_ENVIRONMENT_SLUG-login-chart-pg.review-apps"
},
"postgresWorker": {
"sslmode": "prefer",
"name": "idp",
"host": "$CI_ENVIRONMENT_SLUG-login-chart-pg.review-apps"
},
"railsOffline": "true",
"redis": {
"irsAttemptsApiUrl": "redis://$CI_ENVIRONMENT_SLUG-login-chart-redis.review-apps:6379/2",
"throttleUrl": "redis://$CI_ENVIRONMENT_SLUG-login-chart-redis.review-apps:6379/1",
"url": "redis://$CI_ENVIRONMENT_SLUG-login-chart-redis.review-apps:6379"
},
"assetHost": "https://$CI_ENVIRONMENT_SLUG.reviewapp.identitysandbox.gov",
"domainName": "$CI_ENVIRONMENT_SLUG.reviewapp.identitysandbox.gov",
"loginDatacenter": "true",
"loginDomain": "identitysandbox.gov",
"loginEnv": "$CI_ENVIRONMENT_SLUG",
"loginHostRole": "worker",
"loginSkipRemoteConfig": "true",
"pivcacServiceUrl": "https://$CI_ENVIRONMENT_SLUG.pivcac.reviewapp.identitysandbox.gov/",
"pivcacVerifyTokenUrl": "https://$CI_ENVIRONMENT_SLUG.pivcac.reviewapp.identitysandbox.gov/"
}
EOF
)
- |-
export PIVCAC_CONFIG=$(cat <<EOF
{
"kubernetesReviewApp": "true",
"clientCertS3Bucket": "login-gov-pivcac-public-cert-reviewapps.894947205914-us-west-2",
"postgres": {
"sslmode": "prefer",
"name": "idp",
"host": "$CI_ENVIRONMENT_SLUG-login-chart-pivcac-pg.review-apps"
},
"idpHost": "$CI_ENVIRONMENT_SLUG.reviewapp.identitysandbox.gov",
"domainName": "$CI_ENVIRONMENT_SLUG.pivcac.reviewapp.identitysandbox.gov"
}
EOF
)
- |-
export DASHBOARD_CONFIG=$(cat <<EOF
{
"kubernetesReviewApp": "true",
"postgres": {
"sslmode": "prefer",
"name": "dashboard",
"host": "$CI_ENVIRONMENT_SLUG-login-chart-dashboard-pg.review-apps"
},
"newrelic": {
"enabled": "false"
},
"samlSpIssuer": "https://$CI_ENVIRONMENT_SLUG-dashboard.reviewapp.identitysandbox.gov",
"idpUrl": "https://$CI_ENVIRONMENT_SLUG.reviewapp.identitysandbox.gov",
"idpSpUrl": "https://$CI_ENVIRONMENT_SLUG.reviewapp.identitysandbox.gov",
"postLogoutUrl": "https://$CI_ENVIRONMENT_SLUG-dashboard.reviewapp.identitysandbox.gov",
"domainName": "$CI_ENVIRONMENT_SLUG-dashboard.reviewapp.identitysandbox.gov"
}
EOF
)
- git clone -b main --single-branch https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.login.gov/lg-public/identity-idp-helm-chart.git
- >-
helm upgrade --install --namespace review-apps
--debug
--set env="reviewapps-$CI_ENVIRONMENT_SLUG"
--set idp.image.repository="${ECR_REGISTRY}/identity-idp/review"
--set idp.image.tag="${IDP_IMAGE_TAG}"
--set worker.image.repository="${ECR_REGISTRY}/identity-idp/review"
--set worker.image.tag="${IDP_IMAGE_TAG}"
--set pivcac.image.repository="${ECR_REGISTRY}/identity-pivcac/review"
--set pivcac.image.tag="${PKI_IMAGE_TAG}"
--set pivcac.image.pullPolicy="Always"
--set dashboard.image.repository="${ECR_REGISTRY}/identity-dashboard/review"
--set dashboard.image.tag="${CI_COMMIT_SHA}"
--set dashboard.image.pullPolicy="Always"
--set-json dashboard.config="$DASHBOARD_CONFIG"
--set-json dashboard.enabled=true
--set-json idp.config="$IDP_CONFIG"
--set-json worker.config="$WORKER_CONFIG"
--set-json pivcac.config="$PIVCAC_CONFIG"
--set-json idp.ingress.hosts="[{\"host\": \"$CI_ENVIRONMENT_SLUG.reviewapp.identitysandbox.gov\", \"paths\": [{\"path\": \"/\", \"pathType\": \"Prefix\"}]}]"
--set-json pivcac.ingress.hosts="[{\"host\": \"$CI_ENVIRONMENT_SLUG.pivcac.reviewapp.identitysandbox.gov\", \"paths\": [{\"path\": \"/\", \"pathType\": \"Prefix\"}]}]"
--set-json dashboard.ingress.hosts="[{\"host\": \"$CI_ENVIRONMENT_SLUG-dashboard.reviewapp.identitysandbox.gov\", \"paths\": [{\"path\": \"/\", \"pathType\": \"Prefix\"}]}]"
$CI_ENVIRONMENT_SLUG ./identity-idp-helm-chart
- echo "DNS may take a while to propagate, so be patient if it doesn't show up right away"
- echo "To access the rails console, first run 'aws-vault exec sandbox-power -- aws eks update-kubeconfig --name reviewapp'"
- echo "Then run aws-vault exec sandbox-power -- kubectl exec -it service/$CI_ENVIRONMENT_SLUG-login-chart-idp -n review-apps -- /app/bin/rails console"
- echo "Address of IDP review app:"
- echo https://$CI_ENVIRONMENT_SLUG.reviewapp.identitysandbox.gov
- echo "Address of PIVCAC review app:"
- echo https://$CI_ENVIRONMENT_SLUG.pivcac.reviewapp.identitysandbox.gov
- echo "Address of Dashboard review app:"
- echo https://$CI_ENVIRONMENT_SLUG-dashboard.reviewapp.identitysandbox.gov
environment:
name: review/$CI_COMMIT_REF_NAME
url: https://$CI_ENVIRONMENT_SLUG-dashboard.reviewapp.identitysandbox.gov
on_stop: stop-review-app
auto_stop_in: 2 days
rules:
- if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
- if: $CI_PIPELINE_SOURCE != "merge_request_event"
when: never
stop-review-app:
resource_group: $CI_ENVIRONMENT_SLUG-dashboard.reviewapp.identitysandbox.gov
script:
- export CONTEXT=$(kubectl config get-contexts | grep reviewapp | awk '{print $1}' | head -1)
- kubectl config use-context "$CONTEXT"
- helm uninstall --namespace review-apps $CI_ENVIRONMENT_SLUG
stage: review
image:
name: dtzar/helm-kubectl:latest
needs:
- job: review-app
environment:
name: review/$CI_COMMIT_REF_NAME
action: stop
when: manual
rules:
- if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
- if: $CI_PIPELINE_SOURCE != "merge_request_event"
when: never
include:
- template: Jobs/SAST.gitlab-ci.yml
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
- template: Security/Secret-Detection.gitlab-ci.yml
secret_detection:
stage: scan
allow_failure: false
variables:
SECRET_DETECTION_EXCLUDED_PATHS: 'keys.example,config/artifacts.example,public/acuant/*/opencv.min.js,tmp/0.0.0.0-3000.key'
SECRET_DETECTION_REPORT_FILE: 'gl-secret-detection-report.json'
rules:
- if: $SECRET_DETECTION_DISABLED
when: never
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_TAG'
variables:
SECRET_DETECTION_SHOULD_RUN: "true"
- if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main"
variables:
SECRET_DETECTION_SHOULD_RUN: "true"
SECRET_DETECTION_LOG_OPTIONS: origin/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}..HEAD
- if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != "main" && $CI_EXTERNAL_PULL_REQUEST_TARGET_BRANCH_NAME == "main"
variables:
SECRET_DETECTION_SHOULD_RUN: "true"
SECRET_DETECTION_LOG_OPTIONS: origin/${CI_EXTERNAL_PULL_REQUEST_TARGET_BRANCH_NAME}..HEAD
before_script:
- apk add --no-cache jq
- git fetch origin --quiet
script:
- |
if [ -n "$SECRET_DETECTION_SHOULD_RUN" ]; then
/analyzer run
if [ -f "$SECRET_DETECTION_REPORT_FILE" ]; then
# check if '{ "vulnerabilities": [], ..' is empty in the report file if it exists
if [ "$(jq ".vulnerabilities | length" $SECRET_DETECTION_REPORT_FILE)" -gt 0 ]; then
echo "Vulnerabilities detected. Please analyze the artifact $SECRET_DETECTION_REPORT_FILE produced by the 'secret-detection' job."
exit 80
fi
else
echo "Artifact $SECRET_DETECTION_REPORT_FILE does not exist. The 'secret-detection' job likely didn't create one. Hence, no evaluation can be performed."
fi
else
echo "Skipping because this is not a PR or is not targeting main"
exit 0
fi
# Export the automated ECR scan results into a format Gitlab can use
# Report schema https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/container-scanning-report-format.json
ecr-scan-review-app:
extends: .container_scan_template
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
- if: $CI_PIPELINE_SOURCE != "merge_request_event"
when: never
needs:
- job: build-review-image
stage: scan
variables:
ecr_repo: identity-dashboard/review
ecr-scan-ci:
extends: .container_scan_template
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_PIPELINE_SOURCE == "web"'
changes:
compare_to: 'refs/heads/main'
paths:
- dockerfiles/dashboard_ci.Dockerfile
needs:
- job: build-ci-image
stage: scan
variables:
ecr_repo: dashboard/ci
.container_scan_template:
interruptible: true
allow_failure: true
tags:
- build-pool
image:
name: amazon/aws-cli
entrypoint: [""]
before_script:
- curl -LO https://github.com/jqlang/jq/releases/download/jq-1.6/jq-linux64
- chmod +x jq-linux64
- mv jq-linux64 /usr/local/bin/jq
script:
- >
while true; do
SCAN_STATUS=$(aws ecr describe-image-scan-findings --repository-name ${ecr_repo} --image-id imageTag=$CI_COMMIT_SHA --query 'imageScanStatus.status' --output text || true)
if echo "$SCAN_STATUS" | grep -q "ACTIVE"; then
echo "Scan Complete"
break
elif echo "$SCAN_STATUS" | grep -q "FAILED"; then
echo "ECR scan failed"
exit 1
else
echo "Waiting for ECR scan to complete"
sleep 15
fi
done
- SCAN_FINDINGS=$(aws ecr describe-image-scan-findings --repository-name ${ecr_repo} --image-id imageTag=$CI_COMMIT_SHA)
- echo $SCAN_FINDINGS
- >
echo $SCAN_FINDINGS |
jq -r 'if (.imageScanFindings.enhancedFindings | length > 0) then
{
"version": "15.0.4",
"scan": {
"start_time": (.imageScanFindings.imageScanCompletedAt | sub("\\.[0-9]+"; "") | strptime("%Y-%m-%dT%H:%M:%S%z") | strftime("%Y-%m-%dT%H:%M:%S")),
"end_time": (.imageScanFindings.imageScanCompletedAt | sub("\\.[0-9]+"; "") | strptime("%Y-%m-%dT%H:%M:%S%z") | strftime("%Y-%m-%dT%H:%M:%S")),
"scanner": {
"id": "clair",
"name": "Amazon ECR Image Scan",
"version": "1.0.0",
"vendor": {
"name": "Amazon Web Services"
}
},
"analyzer": {
"id": "clair",
"name": "Amazon ECR Image Scan",
"version": "1.0.0",
"vendor": {
"name": "Amazon Web Services"
}
},
"status": "success",
"type": "container_scanning"
},
"vulnerabilities": [
.imageScanFindings.enhancedFindings[] |
{
"id": .packageVulnerabilityDetails.vulnerabilityId,
"name": .title,
"description": .description,
"severity": (if .severity == "HIGH" then "High"
elif .severity == "MEDIUM" then "Medium"
elif .severity == "LOW" then "Low"
elif .severity == "CRITICAL" then "Critical"
elif .severity == "INFORMATIONAL" then "Info"
elif .severity == "UNTRIAGED" then "Info"
else "Unknown" end),
"solution": .remediation.recommendation.text,
"identifiers": [
{
"type": "cve",
"name": .packageVulnerabilityDetails.vulnerabilityId,
"url": .packageVulnerabilityDetails.sourceUrl,
"value": .packageVulnerabilityDetails.vulnerabilityId
}
],
"links": [
{
"name": .packageVulnerabilityDetails.vulnerabilityId,
"url": .packageVulnerabilityDetails.sourceUrl
}
],
"location": {
"dependency": {
"package": {
"name": .packageVulnerabilityDetails.vulnerablePackages[0].name
},
"version": .packageVulnerabilityDetails.vulnerablePackages[0].version
},
"operating_system": .resources[0].details.awsEcrContainerImage.platform,
"image": .resources[0].id
}
}
]
}
else
{
"version": "15.0.4",
"scan": {
"start_time": (now | strftime("%Y-%m-%dT%H:%M:%S")),
"end_time": (now | strftime("%Y-%m-%dT%H:%M:%S")),
"scanner": {
"id": "clair",
"name": "Amazon ECR Image Scan",
"version": "1.0.0",
"vendor": {
"name": "Amazon Web Services"
}
},
"analyzer": {
"id": "clair",
"name": "Amazon ECR Image Scan",
"version": "1.0.0",
"vendor": {
"name": "Amazon Web Services"
}
},
"status": "success",
"type": "container_scanning"
},
"vulnerabilities": []
}
end' > gl-container-scanning-report.json
artifacts:
paths:
- gl-container-scanning-report.json
reports:
container_scanning: gl-container-scanning-report.json