Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/codeql-evidence-example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ jobs:
# Attaching the evidence to associated package
- name: Attach Evidence using JFrog CLI
run: |
jf config show
if [ ${{ matrix.language_details.name }} == 'go' ]; then
PACKAGE_VERSION="v0.0.${{ github.run_number }}"
jf evd create \
Expand Down
64 changes: 64 additions & 0 deletions .github/workflows/scorecard-evidence-example.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: "Scorecard Evidence Integration example"
on:
workflow_dispatch:

permissions: read-all

jobs:
ossf-scorecard-analysis:
runs-on: ubuntu-latest
env:
REGISTRY_DOMAIN: ${{ vars.JF_URL }}
REPO_NAME: 'docker-scorecard-repo'
IMAGE_NAME: 'docker-scorecard-image'
VERSION: ${{ github.run_number }}
BUILD_NAME: 'scorecard-docker-build'
ATTACH_OPTIONAL_CUSTOM_MARKDOWN_TO_EVIDENCE: true

steps:
# Build and publish the packages to JFrog Artifactory
- name: Setup jfrog cli
uses: jfrog/setup-jfrog-cli@v4
env:
JF_URL: ${{ vars.ARTIFACTORY_URL }}
JF_ACCESS_TOKEN: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
- uses: actions/checkout@v4
with:
sparse-checkout: |
examples/scorecard/**
sparse-checkout-cone-mode: false
- name: Build and publish Docker Image to Artifactory
run: |
docker build . --file ./examples/scorecard/Dockerfile --tag $REGISTRY_DOMAIN/$REPO_NAME/$IMAGE_NAME:$VERSION
echo "Pushing Docker Image to Artifactory"
jf rt docker-push $REGISTRY_DOMAIN/$REPO_NAME/$IMAGE_NAME:$VERSION $REPO_NAME --build-name=$BUILD_NAME --build-number=${{ github.run_number }}
echo "Pushing Docker Image to Artifactory completed"
echo "publishing build info"
jf rt build-publish $BUILD_NAME ${{ github.run_number }}

# Fetch Scorecard Analysis
- name: "Run analysis"
uses: ossf/scorecard-action@v2.4.2
with:
results_file: scorecard-results.sarif
results_format: sarif
publish_results: false

# This is an optional step to generate a custom markdown report
- name: Generate optional custom markdown report
if: env.ATTACH_OPTIONAL_CUSTOM_MARKDOWN_TO_EVIDENCE == 'true'
run: |
python ./examples/scorecard/scorecard_json_to_markdown_helper.py scorecard-results.sarif scorecard-results.md

# Attaching the evidence to associated package
- name: Attach evidence using jfrog cli
run: |
jf evd create \
--package-name $IMAGE_NAME \
--package-version $VERSION \
--package-repo-name $REPO_NAME \
--key "${{ secrets.PRIVATE_KEY }}" \
--key-alias "${{ vars.EVIDENCE_KEY_ALIAS }}" \
--predicate ./scorecard-results.sarif \
--predicate-type http://openssf.org/scorecard/security-scan/v1 \
${{ env.ATTACH_OPTIONAL_CUSTOM_MARKDOWN_TO_EVIDENCE == 'true' && '--markdown "scorecard-results.md"' || '' }}
70 changes: 70 additions & 0 deletions .github/workflows/semgrep-evidence-example.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: "Semgrep Evidence Integration example"
on:
workflow_dispatch:

jobs:
semgrep_scan:
name: semgrep/ci
runs-on: ubuntu-latest
container:
image: semgrep/semgrep
env:
ATTACH_OPTIONAL_CUSTOM_MARKDOWN_TO_EVIDENCE: true
permissions:
security-events: write
actions: read
contents: read

steps:
# Install Node.js and npm
- name: Install Node.js and npm
run: |
apk add --no-cache nodejs npm

# Build and publish the packages to JFrog Artifactory
- name: Setup jfrog cli
uses: jfrog/setup-jfrog-cli@v4
env:
JF_URL: ${{ vars.ARTIFACTORY_URL }}
JF_ACCESS_TOKEN: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
- name: Checkout repository
uses: actions/checkout@v4
with:
sparse-checkout: |
examples/semgrep/**
sparse-checkout-cone-mode: false
- name: Build and Publish js package

run: |
cd examples/semgrep/js
jf npm-config --repo-resolve=javascript-remote --repo-deploy=javascript-local \
--server-id-deploy=setup-jfrog-cli-server \
--server-id-resolve=setup-jfrog-cli-server
jf npm publish --build-name=js-semgrep-sample-build --build-number=${{ github.run_number }}
cd -
continue-on-error: true

# Run Semgrep analysis
- name: Perform Semgrep Analysis
run: |
semgrep scan -q --sarif --config auto ./examples/semgrep/js > semgrep-results.sarif

# This is an optional step to generate a custom markdown report
- name: Generate optional custom markdown
if: env.ATTACH_OPTIONAL_CUSTOM_MARKDOWN_TO_EVIDENCE == 'true'
run: |
python examples/semgrep/sarif_to_markdown.py semgrep-results.sarif semgrep-results.md

# Attaching the evidence to associated package
- name: Attach Evidence using JFrog CLI
run: |
jf evd create \
--package-name js-semgrep-sample-build \
--package-version "0.0.1" \
--package-repo-name javascript-local \
--key "${{ secrets.PRIVATE_KEY }}" \
--key-alias "${{ vars.EVIDENCE_KEY_ALIAS }}" \
--predicate "semgrep-results.sarif" \
--predicate-type "http://semgrep.com/security-scan/v1" \
${{ env.ATTACH_OPTIONAL_CUSTOM_MARKDOWN_TO_EVIDENCE == 'true' && '--markdown "semgrep-results.md"' || '' }}

9 changes: 9 additions & 0 deletions examples/scorecard/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM python:3.7-slim-buster

WORKDIR /app

COPY ./examples/scorecard/requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

CMD ["ansible", "--version"]
86 changes: 86 additions & 0 deletions examples/scorecard/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Scorecard Security Scan Evidence Example

This example demonstrates how to automate Scorecard security scanning for Docker images and attach the scan results as
signed evidence to the image in JFrog Artifactory using GitHub Actions and JFrog CLI.

## Overview

The workflow builds a Docker image, scans it with Scorecard for security and quality metrics, pushes the image to Artifactory, and
attaches the Scorecard scan results as evidence to the image package. This enables traceability and compliance for security
scanning in your CI/CD pipeline.

## Prerequisites

- JFrog CLI 2.65.0 or above (installed automatically in the workflow)
- Artifactory configured as a Docker registry
- The following GitHub repository variables:
- `REGISTRY_DOMAIN` (Artifactory Docker registry domain, e.g. `mycompany.jfrog.io`)
- `ARTIFACTORY_URL` (Artifactory base URL)
- `EVIDENCE_KEY_ALIAS` (Key alias for signing evidence)
- The following GitHub repository secrets:
- `ARTIFACTORY_ACCESS_TOKEN` (Artifactory access token)
- `PRIVATE_KEY` (Private key for signing evidence)

## Environment Variables Used

- `REGISTRY_DOMAIN` - Docker registry domain

## Workflow

```mermaid
graph TD
A[Workflow Dispatch Trigger] --> B[Setup JFrog CLI]
B --> C[Checkout Repository]
C --> D[Build and Publish Docker Image to Artifactory]
D --> E[Run Scorecard Analysis]
E --> F{Attach Optional Custom Markdown Report?}
F -->|Yes| G[Generate Custom Markdown Report]
F -->|No| H[Skip Markdown Report]
G --> I[Attach Evidence to Package]
H --> I[Attach Evidence to Package]
```

## Example Usage

You can trigger the workflow manually from the GitHub Actions tab. The workflow will:

- Build and scan the Docker image
- Push the image to Artifactory
- Attach the Scorecard scan results as evidence

## Key Commands Used

- **Build Docker Image:**
```bash
docker build . --file ./examples/scorecard/Dockerfile --tag $REGISTRY_URL/$REPO_NAME/$IMAGE_NAME:$VERSION
```
- **Run Scorecard Analysis:**
```yaml
uses: ossf/scorecard-action@v2.4.2
with:
results_file: scorecard-results.sarif
results_format: sarif
publish_results: false
```
- **Push Docker Image:**
```bash
jf rt docker-push $REGISTRY_URL/$REPO_NAME/$IMAGE_NAME:$VERSION $REPO_NAME --build-name=$BUILD_NAME --build-number=${{ github.run_number }}
```
- **Attach Evidence:**
```bash
jf evd create \
--package-name $IMAGE_NAME \
--package-version $VERSION \
--package-repo-name $REPO_NAME \
--key "${{ secrets.PRIVATE_KEY }}" \
--key-alias "${{ vars.EVIDENCE_KEY_ALIAS }}" \
--predicate ./scorecard-results.sarif \
--predicate-type http://openssf.org/scorecard/security-scan/v1 \
${{ env.ATTACH_OPTIONAL_CUSTOM_MARKDOWN_TO_EVIDENCE == 'true' && '--markdown "scorecard-results.md"' || '' }}
```

## References

- [Scorecard Documentation](https://github.com/ossf/scorecard)
- [JFrog Evidence Management](https://jfrog.com/help/r/jfrog-artifactory-documentation/evidence-management)
- [JFrog CLI Documentation](https://jfrog.com/getcli/)
1 change: 1 addition & 0 deletions examples/scorecard/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ansible==2.9.9
47 changes: 47 additions & 0 deletions examples/scorecard/scorecard_json_to_markdown_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import json
from datetime import datetime

def convert_report_to_markdown(input_file, output_file):
"""
Converts the Scorecard report.json file to a Markdown file with tabular formatting for lists.

Args:
input_file (str): Path to the input JSON file.
output_file (str): Path to the output Markdown file.
"""
with open(input_file, 'r') as f:
report_data = json.load(f)

markdown_lines = ["# Scorecard Analysis Report", ""]

# Add metadata
markdown_lines.append(f"**Generated on**: {datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S UTC')}")
markdown_lines.append("\n---\n")

# Process runs
for run in report_data.get('runs', []):
tool_name = run.get('tool', {}).get('driver', {}).get('name', 'Unknown Tool')
tool_version = run.get('tool', {}).get('driver', {}).get('semanticVersion', 'Unknown Version')
markdown_lines.append(f"## Tool: {tool_name} (Version: {tool_version})")

# Add results in tabular format
markdown_lines.append("\n| Rule ID | Message |")
markdown_lines.append("|---------|---------|")
for result in run.get('results', []):
rule_id = result.get('ruleId', 'Unknown Rule')
message = result.get('message', {}).get('text', 'No message provided').replace("\n", "<br>")
markdown_lines.append(f"| {rule_id} | {message} |")

# Write to Markdown file
with open(output_file, 'w') as f:
f.write('\n'.join(markdown_lines))

if __name__ == "__main__":
import sys
if len(sys.argv) != 3:
print("Usage: python report_to_markdown.py <input_json_file> <output_markdown_file>")
sys.exit(1)

input_json = sys.argv[1]
output_md = sys.argv[2]
convert_report_to_markdown(input_json, output_md)
78 changes: 78 additions & 0 deletions examples/semgrep/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Semgrep Security Scan Evidence Example

This example demonstrates how to automate Semgrep security scanning for JavaScript code and attach the scan results as signed evidence to the package in JFrog Artifactory using GitHub Actions and JFrog CLI.

## Overview

The workflow scans JavaScript code with Semgrep for security issues, publishes the package to Artifactory, and attaches the Semgrep scan results as evidence to the package. This enables traceability and compliance for security scanning in your CI/CD pipeline.

## Prerequisites

- JFrog CLI 2.65.0 or above (installed automatically in the workflow)
- Artifactory configured as a repository
- The following GitHub repository variables:
- `ARTIFACTORY_URL` (Artifactory base URL)
- `EVIDENCE_KEY_ALIAS` (Key alias for signing evidence)
- The following GitHub repository secrets:
- `ARTIFACTORY_ACCESS_TOKEN` (Artifactory access token)
- `PRIVATE_KEY` (Private key for signing evidence)

## Environment Variables Used

- `ATTACH_OPTIONAL_CUSTOM_MARKDOWN_TO_EVIDENCE` - Whether to attach a custom markdown report to the evidence

## Workflow

```mermaid
graph TD
A[Workflow Dispatch Trigger] --> B[Setup JFrog CLI]
B --> C[Checkout Repository]
C --> D[Publish JavaScript Package to Artifactory]
D --> E[Run Semgrep Security Scan]
E --> F{Attach Optional Custom Markdown Report?}
F -->|Yes| G[Generate Custom Markdown Report]
F -->|No| H[Skip Markdown Report]
G --> I[Attach Evidence Using JFrog CLI]
H --> I[Attach Evidence Using JFrog CLI]
```

## Example Usage

You can trigger the workflow manually from the GitHub Actions tab. The workflow will:

- Scan the JavaScript code
- Publish the package to Artifactory
- Attach the Semgrep scan results as evidence

## Key Commands Used

- **Publish JavaScript Package:**
```bash
jf npm-config --repo-resolve=javascript-remote --repo-deploy=javascript-local \
--server-id-deploy=setup-jfrog-cli-server \
--server-id-resolve=setup-jfrog-cli-server
jf npm publish --build-name=js-semgrep-sample-build --build-number=${{ github.run_number }}
jf rt bp js-semgrep-sample-build ${{ github.run_number }}
```
- **Run Semgrep Scan:**
```bash
semgrep scan -q --sarif --config auto ./examples/semgrep/js > semgrep-results.sarif
```
- **Attach Evidence:**
```bash
jf evd create \
--package-name js-semgrep-sample-build \
--package-version "0.0.1" \
--package-repo-name javascript-local \
--key "${{ secrets.PRIVATE_KEY }}" \
--key-alias "${{ vars.EVIDENCE_KEY_ALIAS }}" \
--predicate "results-javascript/javascript.sarif" \
--predicate-type "http://semgrep.com/security-scan/v1" \
${{ env.ATTACH_OPTIONAL_CUSTOM_MARKDOWN_TO_EVIDENCE == 'true' && '--markdown "results-javascript/javascript-report.md"' || '' }}
```

## References

- [Semgrep Documentation](https://semgrep.dev/docs/)
- [JFrog Evidence Management](https://jfrog.com/help/r/jfrog-artifactory-documentation/evidence-management)
- [JFrog CLI Documentation](https://jfrog.com/getcli/)
3 changes: 3 additions & 0 deletions examples/semgrep/js/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function evaluate(a, b, operation) {
return eval(`(${a}) ${operation} (${b})`);
}
11 changes: 11 additions & 0 deletions examples/semgrep/js/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "js-semgrep-sample-build",
"version": "0.0.1",
"description": "Dummy package for testing semgrep",
"main": "index.js",
"scripts": {
},
"keywords": [],
"author": "JFrog",
"license": "ISC"
}
Loading