Baseline untested container for scanning and reporting on diffs from trivy scans on target hosts on a schedule.

This commit is contained in:
colin 2024-01-18 14:50:27 +00:00 committed by Colin
parent 3c0d12b225
commit b38983d166
7 changed files with 324 additions and 9 deletions

144
.woodpecker.yml Normal file
View File

@ -0,0 +1,144 @@
labels:
hostname: "macmini7"
clone:
git:
image: woodpeckerci/plugin-git
settings:
partial: false
depth: 1
steps:
# Build Step for staging Branch
build-staging:
name: build-staging
image: woodpeckerci/plugin-docker-buildx
secrets: [REGISTRY_USER, REGISTRY_PASSWORD]
volumes:
- /var/run/docker.sock:/var/run/docker.sock
commands:
- echo "Building application for staging branch"
- echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us
- echo compose build
- docker compose -f docker-compose.staging.yml build
when:
branch: main
event: push
# path:
# include: [ 'stack.production.yml', 'stack.staging.yml', 'docker-compose.staging.yml', 'docker-compose.production.yml', 'Dockerfile', '*.tests.ts' ]
deploy-new:
name: deploy-new
when:
branch: main
# path:
# include: [ 'stack.production.yml', 'stack.staging.yml', 'docker-compose.staging.yml', 'docker-compose.production.yml', 'Dockerfile', '*.tests.ts' ]
image: woodpeckerci/plugin-docker-buildx
secrets: [REGISTRY_USER, REGISTRY_PASSWORD]
volumes:
- /var/run/docker.sock:/var/run/docker.sock
commands:
- echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us
- echo compose push
- docker compose -f docker-compose.staging.yml push
# - docker stack deploy --with-registry-auth -c ./stack.staging.yml $${CI_REPO_NAME}-staging
# # Wait for Deploy to Complete
# wait-for-deploy-staging:
# name: wait-for-deploy-staging
# image: woodpeckerci/plugin-git
# commands:
# - echo "Waiting for staging deploy step to complete rollout."
# - sleep 60
# when:
# - branch: main
# - event: push
# # Run Automated Tests on staging Branch
# test-staging:
# name: run-tests-staging
# image: git.nixc.us/colin/playwright:latest
# secrets: [ base_url ]
# when:
# - branch: main
# - event: push
# - path:
# include: [ 'tests/', 'src/','docker-compose.staging.yml', 'docker-compose.production.yml', '*.tests.ts' ] # Specify paths relevant to tests
# volumes:
# - /var/run/docker.sock:/var/run/docker.sock:ro
cleanup-staging:
name: cleanup-staging
when:
branch: main
# path:
# include: [ 'stack.production.yml', 'stack.staging.yml', 'docker-compose.staging.yml', 'docker-compose.production.yml', 'Dockerfile', '*.tests.ts' ]
image: woodpeckerci/plugin-docker-buildx
secrets: [REGISTRY_USER, REGISTRY_PASSWORD]
volumes:
- /var/run/docker.sock:/var/run/docker.sock
commands:
# - docker stack rm $${CI_REPO_NAME}-staging
## added fault tolerance for docker stack rm
# - for i in {1..5}; do docker stack rm ${CI_REPO_NAME}-staging && break || sleep 10; done
- docker compose -f docker-compose.staging.yml down
- docker compose -f docker-compose.staging.yml rm -f
# Build Step for staging Branch
build-build-push-production:
name: build-build-push-production
image: woodpeckerci/plugin-docker-buildx
secrets: [REGISTRY_USER, REGISTRY_PASSWORD]
volumes:
- /var/run/docker.sock:/var/run/docker.sock
commands:
- echo "Building application for staging branch"
- echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us
- echo compose build
- docker compose -f docker-compose.production.yml build --no-cache
- docker compose -f docker-compose.production.yml push
when:
branch: main
event: [push, cron]
# path:
# include: [ 'stack.production.yml', 'stack.staging.yml', 'docker-compose.staging.yml', 'docker-compose.production.yml', 'Dockerfile', '*.tests.ts' ]
# Deploy to Production Branch
deploy-production:
name: deploy-production
image: woodpeckerci/plugin-docker-buildx
secrets: [REGISTRY_USER, REGISTRY_PASSWORD]
volumes:
- /var/run/docker.sock:/var/run/docker.sock
commands:
- echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us
# - docker stack deploy --with-registry-auth -c ./stack.production.yml $${CI_REPO_NAME}
- docker image rm git.nixc.us/colin/$${CI_REPO_NAME}:production
when:
branch: main
event: [push, cron]
# path:
# include: [ 'stack.production.yml', 'stack.staging.yml', 'docker-compose.staging.yml', 'docker-compose.production.yml', 'Dockerfile', '*.tests.ts' ]
# # Wait for Deploy to Complete
# wait-for-deploy-production:
# name: wait-for-deploy-production
# image: woodpeckerci/plugin-git
# commands:
# - echo "Waiting for deploy step to complete rollout."
# - sleep 60
# when:
# branch: main
# event: push
# # Run Post-Deployment Smoke Tests
# post-deploy-smoke-tests-git-nixc-us:
# name: run-post-deploy-smoke-tests-git-nixc-us
# image: git.nixc.us/colin/playwright:latest
# # secrets: [TEST_USER, TEST_PASSWORD]
# environment:
# - BASE_URL=https://git.nixc.us
# when:
# branch: main
# event: push
# # path:
# # include: [ 'stack.production.yml', 'stack.staging.yml', 'docker-compose.staging.yml', 'docker-compose.production.yml', 'Dockerfile', '*.tests.ts' ]

95
README.md Normal file
View File

@ -0,0 +1,95 @@
<!-- # build:0 -->
# Known Weaknesses and Caveats
While this Trivy container is built with reliability in mind, it's important to note that it primarily focuses on scanning and reporting. There isn't an advanced validation mechanism beyond ensuring that the container builds and runs the scans correctly. Future improvements include more robust testing and validation measures.
## ToDo
* [ ] Implement more comprehensive testing beyond basic functionality.
* [ ] Integrate safe testing with known vulnerable files for end-to-end testing.
* [ ] Develop a consistent reporting system for scan results.
* [ ] Experiment with and test quarantine measures for identified vulnerabilities.
## Disclaimer
Understanding the scope and limitations of a vulnerability scanner like Trivy is crucial. A Trivy scan aims to increase observability and enable actions on detectable vulnerabilities, not guarantee future system security. Positive detections should prompt IT staff to consider appropriate remediation steps.
## Considerations
Trivy, running as a Docker container, offers a certain level of security and obscurity. Its cryptographic signature and isolation from typical user space make it a less likely target for tampering by advanced attackers. While it includes a mode for potential quarantine actions, this feature is more theoretical. It has yet to be extensively tested in its current form. Users should exercise caution and use scan logs as a guide for manual file handling if necessary.
# Usage
Create a directory for the Trivy container configuration:
```
mkdir -p /root/trivy/
```
Then edit the Docker Compose file:
```
nano /root/trivy/docker-compose.yml
```
## Environment Variables and Defaults
| Variable | Description | Default Value |
|----------------|----------------------------------------------|------------------------|
| `TIMEOUT` | Maximum duration for a scan | `120m` |
| `SCANNERS` | Scanners to be used | `vuln,misconfig,secret`|
| `IGNORE_UNFIXED`| Whether to ignore vulnerabilities without fixes | `false` |
| `LOW_PRIORITY` | Run scans with low CPU priority (nice 19) | `true` |
### Note:
By default, the container assumes a low-priority mode for scanning if the `LOW_PRIORITY` environment variable is not explicitly set.
## docker-compose.yml
```yaml
version: '3.8'
services:
trivy:
image: aquasec/trivy
volumes:
- /:/mnt:ro
- ./logs:/var/log/trivy
# Uncomment and modify the following lines to customize environment variables
# environment:
# TIMEOUT: "120m" # Default scan timeout
# SCANNERS: "vuln,misconfig,secret" # Scanners to be used
# IGNORE_UNFIXED: "false" # Whether to ignore unfixed vulnerabilities
# LOW_PRIORITY: "true" # Run scans with low CPU priority
```
Schedule regular scans using crontab:
```
crontab -e
```
Then add one of the following cron examples.
### Once a Week
To run the job every Sunday at midnight:
```cron
0 0 * * 0 /usr/bin/docker compose -f /root/trivy/docker-compose.yml up -d --pull --force-recreate trivy
```
### Once Every Two Weeks
For a bi-weekly schedule, specify two days of the month, like the 1st and 15th:
```cron
0 0 1,15 * * /usr/bin/docker compose -f /root/trivy/docker-compose.yml up -d --pull --force-recreate trivy
```
### Once a Month
To run the job on the first day of every month at midnight:
```cron
0 0 1 * * /usr/bin/docker compose -f /root/trivy/docker-compose.yml up -d --pull --force-recreate trivy
```
### Notes:
- Verify that `/usr/bin/docker` is the correct path to your Docker binary. This path might vary.
- Replace `/root/trivy` with the directory path where your `docker-compose.yml` file is located.
- The cron jobs will update the `trivy` container according to the specified schedule. Ensure this aligns with your maintenance and update policies.

View File

@ -0,0 +1,8 @@
version: '3.8'
services:
trivy:
build:
context: ./docker/trivy/
dockerfile: Dockerfile
image: git.nixc.us/colin/trivy:production

View File

@ -0,0 +1,8 @@
version: '3.8'
services:
trivy:
build:
context: ./docker/trivy/
dockerfile: Dockerfile
image: git.nixc.us/colin/trivy:staging

View File

@ -1,9 +0,0 @@
FROM alpine:latest
RUN apk add --no-cache clamav clamav-libunrar
RUN freshclam
COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
VOLUME ["/scan"]
VOLUME ["/quarantine"]
VOLUME ["/var/log/clamav"]
ENTRYPOINT ["docker-entrypoint.sh"]

5
docker/trivy/Dockerfile Normal file
View File

@ -0,0 +1,5 @@
FROM aquasec/trivy
WORKDIR /app
COPY start.sh /start.sh
RUN chmod +x /start.sh
ENTRYPOINT ["/bin/sh", "/start.sh"]

64
docker/trivy/start.sh Normal file
View File

@ -0,0 +1,64 @@
#!/bin/sh
TIMEOUT=${TIMEOUT:-120m}
SCANNERS=${SCANNERS:-vuln,misconfig,secret}
IGNORE_UNFIXED=${IGNORE_UNFIXED:-false}
LOW_PRIORITY=${LOW_PRIORITY:-true}
compare_scans() {
echo "Comparing scans..."
PREVIOUS_LOG="/var/log/trivy/previous_scan.log"
CURRENT_LOG="/var/log/trivy/trivy_scan.log"
SCAN_DATE=$(date +%Y.%m.%d)
DIFF_LOG="/var/log/trivy/scandiff.$SCAN_DATE.log"
if [ -f "$PREVIOUS_LOG" ]; then
echo "Previous scan log found. Comparing with current scan..."
diff $PREVIOUS_LOG $CURRENT_LOG > $DIFF_LOG
if [ $? -eq 0 ]; then
echo "No differences found between scans."
report_scan_results false
else
echo "Differences found. Check $DIFF_LOG for more details."
report_scan_results true
fi
else
echo "No previous scan log found. Treating all findings as new."
cp $CURRENT_LOG $DIFF_LOG
report_scan_results true
fi
# Archive current log as previous for next run
cp $CURRENT_LOG $PREVIOUS_LOG
}
report_scan_results() {
is_diff=$1
DIFF_LOG="/var/log/trivy/scandiff.$(date +%Y.%m.%d).log"
if [ "$is_diff" = true ]; then
echo "Scan differences detected:"
cat $DIFF_LOG
else
echo "No differences to report."
fi
}
run_scan() {
if [ "$LOW_PRIORITY" = "true" ]; then
echo "Running Trivy scan with low priority (nice 19)..."
nice -n 19 trivy filesystem --timeout $TIMEOUT --scanners $SCANNERS $( [ "$IGNORE_UNFIXED" = "true" ] && echo '--ignore-unfixed' ) /mnt > $CURRENT_LOG
else
echo "Running Trivy scan..."
trivy filesystem --timeout $TIMEOUT --scanners $SCANNERS $( [ "$IGNORE_UNFIXED" = "true" ] && echo '--ignore-unfixed' ) /mnt > $CURRENT_LOG
fi
}
# Archive existing log for comparison
if [ -f "/var/log/trivy/trivy_scan.log" ]; then
mv /var/log/trivy/trivy_scan.log /var/log/trivy/previous_scan.log
fi
run_scan
compare_scans