|
|
|
|
@ -124,14 +124,10 @@ jobs:
|
|
|
|
|
run: |
|
|
|
|
|
# Install syft
|
|
|
|
|
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
|
|
|
|
|
echo "${{ secrets.HARBOR_TOKEN }}"
|
|
|
|
|
echo "${{ env.REGISTRY }}"
|
|
|
|
|
echo "${{ secrets.HARBOR_USERNAME }}"
|
|
|
|
|
echo "${{ env.IMAGE_NAME }}"
|
|
|
|
|
# Login to registry - use the REGISTRY variable for the URL
|
|
|
|
|
echo "${{ secrets.HARBOR_TOKEN }}" | docker login ${{ env.REGISTRY }} -u '${{ secrets.HARBOR_USERNAME }}' --password-stdin
|
|
|
|
|
# Generate SBOM using latest tag
|
|
|
|
|
syft ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest -o spdx-json > sbom.spdx.json
|
|
|
|
|
|
|
|
|
|
# Generate SBOM using the specific image digest
|
|
|
|
|
syft ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }} -o spdx-json > sbom.spdx.json
|
|
|
|
|
|
|
|
|
|
# Verify SBOM was created
|
|
|
|
|
if [ ! -f sbom.spdx.json ]; then
|
|
|
|
|
echo "Failed to generate SBOM"
|
|
|
|
|
@ -147,83 +143,98 @@ jobs:
|
|
|
|
|
sudo mv oras /usr/local/bin/
|
|
|
|
|
|
|
|
|
|
# Get the image digest from the build step
|
|
|
|
|
IMAGE_DIGEST="${{ steps.build.outputs.image-digest }}"
|
|
|
|
|
IMAGE_DIGEST="${{ steps.build.outputs.digest }}"
|
|
|
|
|
|
|
|
|
|
# Attach SBOM to the specific image digest
|
|
|
|
|
# Try method 1: Use oras attach with proper media type
|
|
|
|
|
echo "Attempting to attach SBOM with oras attach..."
|
|
|
|
|
oras attach ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${IMAGE_DIGEST} \
|
|
|
|
|
--artifact-type application/vnd.cyclonedx+json \
|
|
|
|
|
--annotation "org.opencontainers.artifact.description=SBOM for ${{ env.IMAGE_NAME }}" \
|
|
|
|
|
sbom.spdx.json:application/spdx+json || echo "oras attach failed, trying alternative method..."
|
|
|
|
|
|
|
|
|
|
# Alternative method: Push as separate artifact with clear naming
|
|
|
|
|
echo "Uploading SBOM as separate artifact..."
|
|
|
|
|
oras push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:sbom-${{ github.sha }} \
|
|
|
|
|
--artifact-type application/spdx+json \
|
|
|
|
|
--annotation "org.opencontainers.artifact.description=SBOM for ${{ env.IMAGE_NAME }}@${IMAGE_DIGEST}" \
|
|
|
|
|
--annotation "org.opencontainers.artifact.source=${IMAGE_DIGEST}" \
|
|
|
|
|
sbom.spdx.json:application/spdx+json
|
|
|
|
|
|
|
|
|
|
echo "SBOM attached successfully to image digest: ${IMAGE_DIGEST}"
|
|
|
|
|
echo "SBOM uploaded successfully"
|
|
|
|
|
|
|
|
|
|
# Job 4: Image Security Scan
|
|
|
|
|
scan:
|
|
|
|
|
name: 🛡️ Image Security Scan
|
|
|
|
|
runs-on: ubuntu-latest
|
|
|
|
|
needs: build
|
|
|
|
|
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
|
|
|
|
steps:
|
|
|
|
|
- name: Login to Harbor Registry
|
|
|
|
|
uses: docker/login-action@v3
|
|
|
|
|
with:
|
|
|
|
|
registry: ${{ env.REGISTRY }}
|
|
|
|
|
username: ${{ secrets.HARBOR_USERNAME }}
|
|
|
|
|
password: ${{ secrets.HARBOR_TOKEN }}
|
|
|
|
|
|
|
|
|
|
- name: Run Trivy vulnerability scanner
|
|
|
|
|
uses: aquasecurity/trivy-action@master
|
|
|
|
|
with:
|
|
|
|
|
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
|
|
|
|
|
format: 'sarif'
|
|
|
|
|
output: 'trivy-results.sarif'
|
|
|
|
|
|
|
|
|
|
- name: Generate JSON scan results
|
|
|
|
|
uses: aquasecurity/trivy-action@master
|
|
|
|
|
with:
|
|
|
|
|
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
|
|
|
|
|
format: 'json'
|
|
|
|
|
output: 'trivy-results.json'
|
|
|
|
|
|
|
|
|
|
- name: Upload scan results artifacts
|
|
|
|
|
uses: actions/upload-artifact@v3
|
|
|
|
|
with:
|
|
|
|
|
name: trivy-scan-results
|
|
|
|
|
path: |
|
|
|
|
|
trivy-results.sarif
|
|
|
|
|
trivy-results.json
|
|
|
|
|
|
|
|
|
|
- name: Attach scan results to Harbor image
|
|
|
|
|
run: |
|
|
|
|
|
# Install ORAS
|
|
|
|
|
curl -LO https://github.com/oras-project/oras/releases/download/v1.1.0/oras_1.1.0_linux_amd64.tar.gz
|
|
|
|
|
tar -xzf oras_1.1.0_linux_amd64.tar.gz
|
|
|
|
|
sudo mv oras /usr/local/bin/
|
|
|
|
|
|
|
|
|
|
# Get the image digest from the build job
|
|
|
|
|
IMAGE_DIGEST="${{ needs.build.outputs.digest }}"
|
|
|
|
|
|
|
|
|
|
# Attach SARIF scan results
|
|
|
|
|
oras attach ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${IMAGE_DIGEST} \
|
|
|
|
|
--artifact-type application/sarif+json \
|
|
|
|
|
trivy-results.sarif:application/sarif+json
|
|
|
|
|
|
|
|
|
|
# Attach JSON scan results
|
|
|
|
|
oras attach ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${IMAGE_DIGEST} \
|
|
|
|
|
--artifact-type application/json \
|
|
|
|
|
trivy-results.json:application/json \
|
|
|
|
|
--annotation "scan.type=vulnerability" \
|
|
|
|
|
--annotation "scan.tool=trivy"
|
|
|
|
|
|
|
|
|
|
echo "Scan results attached successfully to image digest: ${IMAGE_DIGEST}"
|
|
|
|
|
|
|
|
|
|
- name: Check for HIGH/CRITICAL vulnerabilities
|
|
|
|
|
uses: aquasecurity/trivy-action@master
|
|
|
|
|
with:
|
|
|
|
|
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
|
|
|
|
|
format: 'json'
|
|
|
|
|
output: 'trivy-critical.json'
|
|
|
|
|
exit-code: '1'
|
|
|
|
|
severity: 'HIGH,CRITICAL'
|
|
|
|
|
scan:
|
|
|
|
|
name: 🛡️ Image Security Scan
|
|
|
|
|
runs-on: ubuntu-latest
|
|
|
|
|
needs: build
|
|
|
|
|
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
|
|
|
|
steps:
|
|
|
|
|
- name: Login to Harbor Registry
|
|
|
|
|
run: |
|
|
|
|
|
echo "${{ secrets.HARBOR_TOKEN }}" | docker login ${{ env.REGISTRY }} -u '${{ secrets.HARBOR_USERNAME }}' --password-stdin
|
|
|
|
|
|
|
|
|
|
- name: Install Trivy
|
|
|
|
|
run: |
|
|
|
|
|
sudo apt-get update
|
|
|
|
|
sudo apt-get install -y wget
|
|
|
|
|
# Get the latest Trivy version dynamically
|
|
|
|
|
TRIVY_VERSION=$(curl -s "https://api.github.com/repos/aquasecurity/trivy/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/' | sed 's/v//')
|
|
|
|
|
wget https://github.com/aquasecurity/trivy/releases/latest/download/trivy_${TRIVY_VERSION}_Linux-64bit.deb
|
|
|
|
|
sudo dpkg -i trivy_${TRIVY_VERSION}_Linux-64bit.deb
|
|
|
|
|
|
|
|
|
|
- name: Run Trivy scan (SARIF)
|
|
|
|
|
run: |
|
|
|
|
|
trivy image --format sarif --output trivy-results.sarif \
|
|
|
|
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.build.outputs.image-digest }}
|
|
|
|
|
|
|
|
|
|
- name: Run Trivy scan (JSON)
|
|
|
|
|
run: |
|
|
|
|
|
trivy image --format json --output trivy-results.json \
|
|
|
|
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.build.outputs.image-digest }}
|
|
|
|
|
|
|
|
|
|
- name: Install ORAS
|
|
|
|
|
run: |
|
|
|
|
|
curl -LO https://github.com/oras-project/oras/releases/download/v1.1.0/oras_1.1.0_linux_amd64.tar.gz
|
|
|
|
|
tar -xzf oras_1.1.0_linux_amd64.tar.gz
|
|
|
|
|
sudo mv oras /usr/local/bin/
|
|
|
|
|
|
|
|
|
|
- name: Attach scan results to Harbor image
|
|
|
|
|
run: |
|
|
|
|
|
IMAGE_DIGEST="${{ needs.build.outputs.image-digest }}"
|
|
|
|
|
|
|
|
|
|
# Attach SARIF results
|
|
|
|
|
oras attach ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${IMAGE_DIGEST} \
|
|
|
|
|
--artifact-type application/sarif+json \
|
|
|
|
|
--annotation "org.opencontainers.artifact.description=Trivy SARIF scan results" \
|
|
|
|
|
trivy-results.sarif:application/sarif+json
|
|
|
|
|
|
|
|
|
|
# Attach JSON results
|
|
|
|
|
oras attach ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${IMAGE_DIGEST} \
|
|
|
|
|
--artifact-type application/json \
|
|
|
|
|
--annotation "scan.type=vulnerability" \
|
|
|
|
|
--annotation "scan.tool=trivy" \
|
|
|
|
|
--annotation "org.opencontainers.artifact.description=Trivy JSON scan results" \
|
|
|
|
|
trivy-results.json:application/json
|
|
|
|
|
|
|
|
|
|
echo "Scan results attached successfully"
|
|
|
|
|
|
|
|
|
|
- name: Upload scan artifacts (backup)
|
|
|
|
|
uses: actions/upload-artifact@v3
|
|
|
|
|
with:
|
|
|
|
|
name: trivy-scan-results
|
|
|
|
|
path: |
|
|
|
|
|
trivy-results.sarif
|
|
|
|
|
trivy-results.json
|
|
|
|
|
|
|
|
|
|
- name: Check for HIGH/CRITICAL vulnerabilities
|
|
|
|
|
run: |
|
|
|
|
|
trivy image \
|
|
|
|
|
--format json \
|
|
|
|
|
--output trivy-critical.json \
|
|
|
|
|
--severity HIGH,CRITICAL \
|
|
|
|
|
--exit-code 1 \
|
|
|
|
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.build.outputs.image-digest }}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# # Job 5: Deploy to Development
|
|
|
|
|
# deploy-dev:
|
|
|
|
|
|