Security improvements and local testing scripts
ci/woodpecker/push/woodpecker Pipeline failed
Details
ci/woodpecker/push/woodpecker Pipeline failed
Details
- Fix Dockerfile to run as non-root user (node) for security - Fix phonetic key generator to always start with consonant (test fix) - Add local security scanning scripts (SBOM, Trivy) - Update test script to exclude security tests from mocha - Add npm scripts for security scans - Update .gitignore for generated files - Update Woodpecker CI to use modern Trivy syntax and push images
This commit is contained in:
parent
69db5d56a5
commit
618a2c1ff7
|
|
@ -4,4 +4,7 @@ node_modules
|
||||||
*.swo
|
*.swo
|
||||||
data
|
data
|
||||||
*.DS_Store
|
*.DS_Store
|
||||||
test-data/
|
test-data/
|
||||||
|
bin/
|
||||||
|
sbom*.txt
|
||||||
|
sbom*.json
|
||||||
|
|
@ -0,0 +1,124 @@
|
||||||
|
labels:
|
||||||
|
location: manager
|
||||||
|
|
||||||
|
clone:
|
||||||
|
git:
|
||||||
|
image: woodpeckerci/plugin-git
|
||||||
|
settings:
|
||||||
|
partial: false
|
||||||
|
depth: 1
|
||||||
|
|
||||||
|
steps:
|
||||||
|
# Run Tests
|
||||||
|
test:
|
||||||
|
name: test
|
||||||
|
image: node:22-alpine
|
||||||
|
commands:
|
||||||
|
- echo "nameserver 1.1.1.1" > /etc/resolv.conf
|
||||||
|
- echo "nameserver 1.0.0.1" >> /etc/resolv.conf
|
||||||
|
- npm --version | cat
|
||||||
|
- node --version | cat
|
||||||
|
- npm ci
|
||||||
|
- npm test
|
||||||
|
when:
|
||||||
|
branch: main
|
||||||
|
event: [push, pull_request, cron]
|
||||||
|
|
||||||
|
# SBOM for source code
|
||||||
|
sbom-source:
|
||||||
|
name: sbom-source
|
||||||
|
image: alpine:3.20
|
||||||
|
commands:
|
||||||
|
- echo "nameserver 1.1.1.1" > /etc/resolv.conf
|
||||||
|
- echo "nameserver 1.0.0.1" >> /etc/resolv.conf
|
||||||
|
- apk add --no-cache curl tar
|
||||||
|
- curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
|
||||||
|
- syft version | cat
|
||||||
|
- syft dir:. -o table | tee sbom.txt
|
||||||
|
- syft dir:. -o spdx-json > sbom.spdx.json
|
||||||
|
- echo "SBOM generated successfully"
|
||||||
|
- ls -lh sbom.* | cat
|
||||||
|
when:
|
||||||
|
branch: main
|
||||||
|
event: [push, pull_request, cron]
|
||||||
|
|
||||||
|
# Trivy filesystem scan
|
||||||
|
trivy-fs:
|
||||||
|
name: trivy-fs
|
||||||
|
image: aquasec/trivy:latest
|
||||||
|
commands:
|
||||||
|
- echo "nameserver 1.1.1.1" > /etc/resolv.conf
|
||||||
|
- echo "nameserver 1.0.0.1" >> /etc/resolv.conf
|
||||||
|
- trivy --version | cat
|
||||||
|
- trivy fs --scanners vuln,misconfig --severity HIGH,CRITICAL --exit-code 0 .
|
||||||
|
- trivy fs --scanners vuln,misconfig --severity HIGH,CRITICAL --exit-code 0 Dockerfile
|
||||||
|
when:
|
||||||
|
branch: main
|
||||||
|
event: [push, pull_request, cron]
|
||||||
|
|
||||||
|
# Build Docker image for scanning
|
||||||
|
build-image:
|
||||||
|
name: build-image
|
||||||
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
|
depends_on: [ "test" ]
|
||||||
|
environment:
|
||||||
|
REGISTRY_USER:
|
||||||
|
from_secret: REGISTRY_USER
|
||||||
|
REGISTRY_PASSWORD:
|
||||||
|
from_secret: REGISTRY_PASSWORD
|
||||||
|
DOCKER_REGISTRY_USER:
|
||||||
|
from_secret: DOCKER_REGISTRY_USER
|
||||||
|
DOCKER_REGISTRY_PASSWORD:
|
||||||
|
from_secret: DOCKER_REGISTRY_PASSWORD
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
commands:
|
||||||
|
- echo "nameserver 1.1.1.1" > /etc/resolv.conf
|
||||||
|
- echo "nameserver 1.0.0.1" >> /etc/resolv.conf
|
||||||
|
- HOSTNAME=$(docker info --format "{{.Name}}")
|
||||||
|
- echo "Building on $HOSTNAME"
|
||||||
|
- echo "$${DOCKER_REGISTRY_PASSWORD}" | docker login -u "$${DOCKER_REGISTRY_USER}" --password-stdin || echo "Docker registry login skipped"
|
||||||
|
- echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us || echo "Registry login skipped"
|
||||||
|
- docker build -t hastebin:test --no-cache .
|
||||||
|
- docker tag hastebin:test git.nixc.us/hastebin:latest || echo "Image tagging skipped"
|
||||||
|
- docker push git.nixc.us/hastebin:latest || echo "Image push skipped (may need registry credentials)"
|
||||||
|
when:
|
||||||
|
branch: main
|
||||||
|
event: [push, cron]
|
||||||
|
|
||||||
|
# Scan Docker image with Trivy
|
||||||
|
trivy-image:
|
||||||
|
name: trivy-image
|
||||||
|
image: aquasec/trivy:latest
|
||||||
|
depends_on: [ "build-image" ]
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
commands:
|
||||||
|
- echo "nameserver 1.1.1.1" > /etc/resolv.conf
|
||||||
|
- echo "nameserver 1.0.0.1" >> /etc/resolv.conf
|
||||||
|
- trivy --version | cat
|
||||||
|
- trivy image --timeout 10m --scanners vuln --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 hastebin:test
|
||||||
|
when:
|
||||||
|
branch: main
|
||||||
|
event: [push, cron]
|
||||||
|
|
||||||
|
# Generate SBOM for Docker image
|
||||||
|
sbom-image:
|
||||||
|
name: sbom-image
|
||||||
|
image: alpine:3.20
|
||||||
|
depends_on: [ "build-image" ]
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
commands:
|
||||||
|
- echo "nameserver 1.1.1.1" > /etc/resolv.conf
|
||||||
|
- echo "nameserver 1.0.0.1" >> /etc/resolv.conf
|
||||||
|
- apk add --no-cache curl docker-cli
|
||||||
|
- curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
|
||||||
|
- syft version | cat
|
||||||
|
- syft docker:hastebin:test -o table | tee sbom-image.txt
|
||||||
|
- syft docker:hastebin:test -o spdx-json > sbom-image.spdx.json
|
||||||
|
- echo "Image SBOM generated successfully"
|
||||||
|
- ls -lh sbom-image.* | cat
|
||||||
|
when:
|
||||||
|
branch: main
|
||||||
|
event: [push, cron]
|
||||||
|
|
@ -21,6 +21,10 @@ RUN node update-js.js || echo "No update-js.js script found"
|
||||||
RUN echo "var config = require('./config.js'); config.storage = { type: 'file', path: '/app/data' }; module.exports = config;" > /app/config.override.js && \
|
RUN echo "var config = require('./config.js'); config.storage = { type: 'file', path: '/app/data' }; module.exports = config;" > /app/config.override.js && \
|
||||||
sed -i '1s/^/var config = require(".\/config.override.js"); /' server.js
|
sed -i '1s/^/var config = require(".\/config.override.js"); /' server.js
|
||||||
|
|
||||||
|
# Change ownership of /app to node user (non-root)
|
||||||
|
# The node user already exists in node:22-alpine (UID 1000)
|
||||||
|
RUN chown -R node:node /app
|
||||||
|
|
||||||
# Set environment variables
|
# Set environment variables
|
||||||
ENV NODE_ENV=production \
|
ENV NODE_ENV=production \
|
||||||
HASTEBIN_STORAGE_TYPE=file \
|
HASTEBIN_STORAGE_TYPE=file \
|
||||||
|
|
@ -34,5 +38,8 @@ ENV NODE_ENV=production \
|
||||||
# Expose port
|
# Expose port
|
||||||
EXPOSE 7777
|
EXPOSE 7777
|
||||||
|
|
||||||
|
# Switch to non-root user
|
||||||
|
USER node
|
||||||
|
|
||||||
# Use app.sh script as entry point
|
# Use app.sh script as entry point
|
||||||
CMD ["/app/app.sh"]
|
CMD ["/app/app.sh"]
|
||||||
|
|
@ -12,7 +12,7 @@ module.exports = class PhoneticKeyGenerator {
|
||||||
|
|
||||||
createKey(keyLength) {
|
createKey(keyLength) {
|
||||||
let text = '';
|
let text = '';
|
||||||
let chooseConsonant = Math.random() < 0.5; // Randomly start with consonant or vowel
|
let chooseConsonant = true; // Always start with consonant
|
||||||
|
|
||||||
for (let i = 0; i < keyLength; i++) {
|
for (let i = 0; i < keyLength; i++) {
|
||||||
text += chooseConsonant ? randConsonant() : randVowel();
|
text += chooseConsonant ? randConsonant() : randVowel();
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
"start": "node server.js",
|
"start": "node server.js",
|
||||||
"start:file": "NODE_ENV=development HASTEBIN_STORAGE_TYPE=file node server.js",
|
"start:file": "NODE_ENV=development HASTEBIN_STORAGE_TYPE=file node server.js",
|
||||||
"start:dev": "NODE_ENV=development HASTEBIN_STORAGE_TYPE=file node server.js",
|
"start:dev": "NODE_ENV=development HASTEBIN_STORAGE_TYPE=file node server.js",
|
||||||
"test": "mocha --recursive",
|
"test": "mocha --recursive --ignore 'test/security/**'",
|
||||||
"test:core": "mocha test/core/core_functionality_spec.js",
|
"test:core": "mocha test/core/core_functionality_spec.js",
|
||||||
"test:security": "node test/security/security_spec.js --test=basic,csp,noCsp,cors,hsts,devMode,devBypass,combinedSecurity",
|
"test:security": "node test/security/security_spec.js --test=basic,csp,noCsp,cors,hsts,devMode,devBypass,combinedSecurity",
|
||||||
"test:all": "npm run test && npm run test:security",
|
"test:all": "npm run test && npm run test:security",
|
||||||
|
|
@ -63,7 +63,12 @@
|
||||||
"test:security:csp": "node test/security/security_spec.js --test=csp",
|
"test:security:csp": "node test/security/security_spec.js --test=csp",
|
||||||
"test:security:cors": "node test/security/security_spec.js --test=cors",
|
"test:security:cors": "node test/security/security_spec.js --test=cors",
|
||||||
"test:security:combined": "node test/security/security_spec.js --test=combinedSecurity",
|
"test:security:combined": "node test/security/security_spec.js --test=combinedSecurity",
|
||||||
"build": "node update-js.js"
|
"build": "node update-js.js",
|
||||||
|
"scan:sbom": "./scripts/scan-sbom.sh",
|
||||||
|
"scan:trivy": "./scripts/scan-trivy-fs.sh",
|
||||||
|
"scan:trivy:image": "./scripts/scan-trivy-image.sh",
|
||||||
|
"scan:sbom:image": "./scripts/scan-sbom-image.sh",
|
||||||
|
"scan:all": "npm run scan:sbom && npm run scan:trivy"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
# Scripts
|
||||||
|
|
||||||
|
This directory contains utility scripts for the Hastebin project.
|
||||||
|
|
||||||
|
## Git Hooks Installation
|
||||||
|
|
||||||
|
### `install-git-hooks.sh`
|
||||||
|
|
||||||
|
Installs Git pre-commit hooks to prevent pushing broken code. The hook runs core tests before each commit.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/install-git-hooks.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**What it does:**
|
||||||
|
|
||||||
|
1. Creates a pre-commit hook in `.git/hooks/pre-commit`
|
||||||
|
2. The hook runs `npm run test:core` before each commit
|
||||||
|
3. If tests fail, the commit is aborted
|
||||||
|
4. Automatically installs dependencies if `node_modules` is missing
|
||||||
|
|
||||||
|
**Skipping the hook:**
|
||||||
|
|
||||||
|
If you need to skip the pre-commit hook (not recommended), use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git commit --no-verify
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** The hook runs core tests only (faster than the full test suite) to keep commit times reasonable. Full tests are still run in CI/CD via Woodpecker.
|
||||||
|
|
||||||
|
## Security Scanning
|
||||||
|
|
||||||
|
### SBOM Generation
|
||||||
|
|
||||||
|
#### `scan-sbom.sh`
|
||||||
|
|
||||||
|
Generates a Software Bill of Materials (SBOM) for the source code using Syft. Creates SBOM files in multiple formats (table, SPDX JSON, CycloneDX JSON).
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/scan-sbom.sh
|
||||||
|
# or
|
||||||
|
npm run scan:sbom
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output files:**
|
||||||
|
- `sbom.txt` - Human-readable table format
|
||||||
|
- `sbom.spdx.json` - SPDX JSON format
|
||||||
|
- `sbom.cyclonedx.json` - CycloneDX JSON format
|
||||||
|
|
||||||
|
**Requirements:**
|
||||||
|
- Syft (automatically installed if not present)
|
||||||
|
|
||||||
|
### Trivy Security Scans
|
||||||
|
|
||||||
|
#### `scan-trivy-fs.sh`
|
||||||
|
|
||||||
|
Runs Trivy filesystem security scan to detect vulnerabilities and misconfigurations in the codebase and Dockerfile.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/scan-trivy-fs.sh
|
||||||
|
# or
|
||||||
|
npm run scan:trivy
|
||||||
|
```
|
||||||
|
|
||||||
|
**What it scans:**
|
||||||
|
- Filesystem for vulnerabilities (HIGH and CRITICAL severity)
|
||||||
|
- Dockerfile for misconfigurations
|
||||||
|
- Reports findings but doesn't fail (exit code 0)
|
||||||
|
|
||||||
|
**Requirements:**
|
||||||
|
- Trivy installed (`brew install trivy` or see [Trivy installation guide](https://aquasecurity.github.io/trivy/latest/getting-started/installation/))
|
||||||
|
|
||||||
|
#### `scan-trivy-image.sh`
|
||||||
|
|
||||||
|
Builds the Docker image and scans it for vulnerabilities using Trivy.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/scan-trivy-image.sh [image-name]
|
||||||
|
# or
|
||||||
|
npm run scan:trivy:image
|
||||||
|
```
|
||||||
|
|
||||||
|
**Default image name:** `hastebin:test`
|
||||||
|
|
||||||
|
**What it does:**
|
||||||
|
1. Builds the Docker image
|
||||||
|
2. Scans the image for vulnerabilities (HIGH and CRITICAL severity)
|
||||||
|
3. Fails if unfixed vulnerabilities are found (exit code 1)
|
||||||
|
|
||||||
|
**Requirements:**
|
||||||
|
- Docker
|
||||||
|
- Trivy installed
|
||||||
|
|
||||||
|
### Image SBOM Generation
|
||||||
|
|
||||||
|
#### `scan-sbom-image.sh`
|
||||||
|
|
||||||
|
Builds the Docker image and generates an SBOM for it.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/scan-sbom-image.sh [image-name]
|
||||||
|
# or
|
||||||
|
npm run scan:sbom:image
|
||||||
|
```
|
||||||
|
|
||||||
|
**Default image name:** `hastebin:test`
|
||||||
|
|
||||||
|
**Output files:**
|
||||||
|
- `sbom-image.txt` - Human-readable table format
|
||||||
|
- `sbom-image.spdx.json` - SPDX JSON format
|
||||||
|
- `sbom-image.cyclonedx.json` - CycloneDX JSON format
|
||||||
|
|
||||||
|
**Requirements:**
|
||||||
|
- Docker
|
||||||
|
- Syft (automatically installed if not present)
|
||||||
|
|
||||||
|
### Running All Scans
|
||||||
|
|
||||||
|
To run both SBOM generation and Trivy filesystem scan:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run scan:all
|
||||||
|
```
|
||||||
|
|
||||||
|
This runs:
|
||||||
|
1. SBOM generation for source code
|
||||||
|
2. Trivy filesystem security scan
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Installation script for Git hooks in Hastebin
|
||||||
|
# This script sets up pre-commit hooks to prevent pushing broken code
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Get the repository root
|
||||||
|
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo "$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)")
|
||||||
|
HOOKS_DIR="$REPO_ROOT/.git/hooks"
|
||||||
|
PRE_COMMIT_HOOK="$HOOKS_DIR/pre-commit"
|
||||||
|
SCRIPT_DIR="$REPO_ROOT/scripts"
|
||||||
|
|
||||||
|
echo -e "${BLUE}🔧 Installing Git hooks for Hastebin${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if we're in a git repository
|
||||||
|
if [ ! -d "$REPO_ROOT/.git" ]; then
|
||||||
|
echo -e "${RED}❌ Error: Not a git repository${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create hooks directory if it doesn't exist
|
||||||
|
mkdir -p "$HOOKS_DIR"
|
||||||
|
|
||||||
|
# Check if pre-commit hook already exists
|
||||||
|
if [ -f "$PRE_COMMIT_HOOK" ]; then
|
||||||
|
echo -e "${YELLOW}⚠️ Pre-commit hook already exists${NC}"
|
||||||
|
read -p "Do you want to overwrite it? (y/N): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo -e "${YELLOW}Skipping hook installation${NC}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
# Backup existing hook
|
||||||
|
mv "$PRE_COMMIT_HOOK" "$PRE_COMMIT_HOOK.backup.$(date +%Y%m%d_%H%M%S)"
|
||||||
|
echo -e "${YELLOW}Backed up existing hook${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create the pre-commit hook
|
||||||
|
cat > "$PRE_COMMIT_HOOK" << 'HOOK_EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Git pre-commit hook for Hastebin
|
||||||
|
# Runs tests before allowing commits to prevent pushing broken code
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Running pre-commit checks...${NC}"
|
||||||
|
|
||||||
|
# Get the repository root
|
||||||
|
REPO_ROOT=$(git rev-parse --show-toplevel)
|
||||||
|
cd "$REPO_ROOT"
|
||||||
|
|
||||||
|
# Check if node_modules exists, if not, install dependencies
|
||||||
|
if [ ! -d "node_modules" ]; then
|
||||||
|
echo -e "${YELLOW}Installing dependencies...${NC}"
|
||||||
|
npm ci
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run the core tests (faster than full test suite)
|
||||||
|
echo -e "${YELLOW}Running core tests...${NC}"
|
||||||
|
if npm run test:core; then
|
||||||
|
echo -e "${GREEN}✅ Core tests passed${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}❌ Core tests failed. Commit aborted.${NC}"
|
||||||
|
echo -e "${YELLOW}To skip this check, use: git commit --no-verify${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean up test artifacts
|
||||||
|
if [ -d "test-data" ]; then
|
||||||
|
rm -rf test-data
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}✅ Pre-commit checks passed${NC}"
|
||||||
|
exit 0
|
||||||
|
HOOK_EOF
|
||||||
|
|
||||||
|
# Make the hook executable
|
||||||
|
chmod +x "$PRE_COMMIT_HOOK"
|
||||||
|
|
||||||
|
echo -e "${GREEN}✅ Pre-commit hook installed successfully${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}The hook will now run tests before each commit.${NC}"
|
||||||
|
echo -e "${YELLOW}To skip the hook, use: git commit --no-verify${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if dependencies are installed
|
||||||
|
if [ ! -d "$REPO_ROOT/node_modules" ]; then
|
||||||
|
echo -e "${YELLOW}⚠️ Dependencies not found. Installing...${NC}"
|
||||||
|
cd "$REPO_ROOT"
|
||||||
|
npm ci
|
||||||
|
echo -e "${GREEN}✅ Dependencies installed${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}🎉 Git hooks installation complete!${NC}"
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Generate SBOM for Docker image
|
||||||
|
# Builds the image and generates SBOM in multiple formats
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
IMAGE_NAME="${1:-hastebin:test}"
|
||||||
|
|
||||||
|
echo "🐳 Building Docker image: $IMAGE_NAME"
|
||||||
|
docker build -t "$IMAGE_NAME" --no-cache .
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🔍 Generating SBOM for Docker image..."
|
||||||
|
|
||||||
|
# Check if syft is installed
|
||||||
|
if ! command -v syft &> /dev/null; then
|
||||||
|
echo "Syft not found. Attempting to install to ./bin..."
|
||||||
|
mkdir -p ./bin
|
||||||
|
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b ./bin
|
||||||
|
export PATH="./bin:$PATH"
|
||||||
|
|
||||||
|
# Verify installation
|
||||||
|
if ! command -v syft &> /dev/null; then
|
||||||
|
echo "❌ Failed to install syft automatically."
|
||||||
|
echo "Please install manually:"
|
||||||
|
echo " brew install syft"
|
||||||
|
echo " or visit: https://github.com/anchore/syft#installation"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Show version
|
||||||
|
syft version
|
||||||
|
|
||||||
|
# Generate SBOM in table format
|
||||||
|
echo ""
|
||||||
|
echo "📋 Generating SBOM table..."
|
||||||
|
syft docker:"$IMAGE_NAME" -o table | tee sbom-image.txt
|
||||||
|
|
||||||
|
# Generate SBOM in SPDX JSON format
|
||||||
|
echo ""
|
||||||
|
echo "📦 Generating SBOM in SPDX JSON format..."
|
||||||
|
syft docker:"$IMAGE_NAME" -o spdx-json > sbom-image.spdx.json
|
||||||
|
|
||||||
|
# Generate SBOM in CycloneDX JSON format
|
||||||
|
echo ""
|
||||||
|
echo "🌀 Generating SBOM in CycloneDX JSON format..."
|
||||||
|
syft docker:"$IMAGE_NAME" -o cyclonedx-json > sbom-image.cyclonedx.json
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✅ Image SBOM generated successfully!"
|
||||||
|
echo ""
|
||||||
|
echo "Generated files:"
|
||||||
|
ls -lh sbom-image.* | cat
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Generate SBOM (Software Bill of Materials) for source code
|
||||||
|
# Uses Syft to generate SBOM in multiple formats
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "🔍 Generating SBOM for source code..."
|
||||||
|
|
||||||
|
# Check if syft is installed
|
||||||
|
if ! command -v syft &> /dev/null; then
|
||||||
|
echo "Syft not found. Attempting to install to ./bin..."
|
||||||
|
mkdir -p ./bin
|
||||||
|
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b ./bin
|
||||||
|
export PATH="./bin:$PATH"
|
||||||
|
|
||||||
|
# Verify installation
|
||||||
|
if ! command -v syft &> /dev/null; then
|
||||||
|
echo "❌ Failed to install syft automatically."
|
||||||
|
echo "Please install manually:"
|
||||||
|
echo " brew install syft"
|
||||||
|
echo " or visit: https://github.com/anchore/syft#installation"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Show version
|
||||||
|
syft version
|
||||||
|
|
||||||
|
# Generate SBOM in table format
|
||||||
|
echo ""
|
||||||
|
echo "📋 Generating SBOM table..."
|
||||||
|
syft dir:. -o table | tee sbom.txt
|
||||||
|
|
||||||
|
# Generate SBOM in SPDX JSON format
|
||||||
|
echo ""
|
||||||
|
echo "📦 Generating SBOM in SPDX JSON format..."
|
||||||
|
syft dir:. -o spdx-json > sbom.spdx.json
|
||||||
|
|
||||||
|
# Generate SBOM in CycloneDX JSON format
|
||||||
|
echo ""
|
||||||
|
echo "🌀 Generating SBOM in CycloneDX JSON format..."
|
||||||
|
syft dir:. -o cyclonedx-json > sbom.cyclonedx.json
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✅ SBOM generated successfully!"
|
||||||
|
echo ""
|
||||||
|
echo "Generated files:"
|
||||||
|
ls -lh sbom.* | cat
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Run Trivy filesystem security scan
|
||||||
|
# Scans for vulnerabilities and misconfigurations
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "🔒 Running Trivy filesystem security scan..."
|
||||||
|
|
||||||
|
# Check if trivy is installed
|
||||||
|
if ! command -v trivy &> /dev/null; then
|
||||||
|
echo "Trivy not found. Please install it:"
|
||||||
|
echo " brew install trivy"
|
||||||
|
echo " or visit: https://aquasecurity.github.io/trivy/latest/getting-started/installation/"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Show version
|
||||||
|
trivy --version
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "📁 Scanning filesystem for vulnerabilities and misconfigurations..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Scan filesystem with exit code 0 (don't fail on findings, just report)
|
||||||
|
trivy fs \
|
||||||
|
--scanners vuln,misconfig \
|
||||||
|
--severity HIGH,CRITICAL \
|
||||||
|
--exit-code 0 \
|
||||||
|
--format table \
|
||||||
|
.
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🐳 Scanning Dockerfile..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Scan Dockerfile
|
||||||
|
trivy fs \
|
||||||
|
--scanners vuln,misconfig \
|
||||||
|
--severity HIGH,CRITICAL \
|
||||||
|
--exit-code 0 \
|
||||||
|
--format table \
|
||||||
|
Dockerfile
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✅ Trivy filesystem scan completed!"
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Run Trivy image security scan
|
||||||
|
# Builds the Docker image and scans it for vulnerabilities
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
IMAGE_NAME="${1:-hastebin:test}"
|
||||||
|
|
||||||
|
echo "🐳 Building Docker image: $IMAGE_NAME"
|
||||||
|
docker build -t "$IMAGE_NAME" --no-cache .
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🔒 Running Trivy image security scan..."
|
||||||
|
|
||||||
|
# Check if trivy is installed
|
||||||
|
if ! command -v trivy &> /dev/null; then
|
||||||
|
echo "Trivy not found. Please install it:"
|
||||||
|
echo " brew install trivy"
|
||||||
|
echo " or visit: https://aquasecurity.github.io/trivy/latest/getting-started/installation/"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Show version
|
||||||
|
trivy --version
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "📦 Scanning Docker image for vulnerabilities..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Scan image with exit code 1 (fail on HIGH/CRITICAL vulnerabilities)
|
||||||
|
trivy image \
|
||||||
|
--timeout 10m \
|
||||||
|
--scanners vuln \
|
||||||
|
--severity HIGH,CRITICAL \
|
||||||
|
--ignore-unfixed \
|
||||||
|
--exit-code 1 \
|
||||||
|
--format table \
|
||||||
|
"$IMAGE_NAME"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✅ Trivy image scan completed!"
|
||||||
Loading…
Reference in New Issue