Skip to content

Commit 258c98d

Browse files
authored
Merge pull request #1 from kusaridev/pxp928-add-ci-template
add ci template for gitlab and github
2 parents 1193133 + d657fed commit 258c98d

File tree

4 files changed

+388
-1
lines changed

4 files changed

+388
-1
lines changed
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# Kusari GitHub Actions Reusable Workflow
2+
#
3+
# This workflow provides automated security scanning for pull requests using Kusari Inspector.
4+
# It automatically posts scan results as comments on pull requests when issues are found.
5+
#
6+
# USAGE:
7+
# Create a workflow file in your repository (e.g., .github/workflows/kusari-scan.yml):
8+
#
9+
# name: Kusari Security Scan
10+
# on:
11+
# pull_request:
12+
# branches: [main, master]
13+
#
14+
# jobs:
15+
# kusari-scan:
16+
# uses: kusaridev/kusari-ci-templates/.github/workflows/kusari-scan-v1.yml@v1
17+
# permissions:
18+
# contents: read
19+
# pull-requests: write
20+
# secrets:
21+
# KUSARI_CLIENT_ID: ${{ secrets.KUSARI_CLIENT_ID }}
22+
# KUSARI_CLIENT_SECRET: ${{ secrets.KUSARI_CLIENT_SECRET }}
23+
# with:
24+
# fail_on_issues: false
25+
# post_comment: true
26+
#
27+
# REQUIRED SECRETS (set in GitHub repository/organization settings):
28+
# - KUSARI_CLIENT_ID: Your Kusari client ID
29+
# - KUSARI_CLIENT_SECRET: Your Kusari client secret
30+
#
31+
# REQUIRED PERMISSIONS:
32+
# The calling workflow MUST specify these permissions:
33+
# permissions:
34+
# contents: read # Required to checkout code
35+
# pull-requests: write # Required to post PR comments
36+
#
37+
# OPTIONAL INPUTS:
38+
# - kusari_cli_image: Override the default Kusari CLI image
39+
# - fail_on_issues: Set to true to fail workflow on security issues (default: false)
40+
# - post_comment: Set to true to post results as PR comment (default: true)
41+
42+
name: Kusari Security Scan
43+
44+
on:
45+
workflow_call:
46+
inputs:
47+
kusari_cli_image:
48+
description: 'Kusari CLI container image'
49+
required: false
50+
type: string
51+
default: 'ghcr.io/kusaridev/kusari-cli@sha256:955262cae4d161f68cb623b273cb9a3d589004a2e7f661b15ff0d1697e494903'
52+
fail_on_issues:
53+
description: 'Fail workflow if security issues are found'
54+
required: false
55+
type: boolean
56+
default: false
57+
post_comment:
58+
description: 'Post scan results as PR comment'
59+
required: false
60+
type: boolean
61+
default: true
62+
secrets:
63+
KUSARI_CLIENT_ID:
64+
description: 'Kusari client ID'
65+
required: true
66+
KUSARI_CLIENT_SECRET:
67+
description: 'Kusari client secret'
68+
required: true
69+
70+
jobs:
71+
kusari-scan:
72+
name: Kusari Security Scan
73+
runs-on: ubuntu-latest
74+
container:
75+
image: ${{ inputs.kusari_cli_image }}
76+
77+
steps:
78+
- name: Install dependencies
79+
run: apk add --no-cache git jq gnutar bzip2
80+
81+
- name: Checkout code
82+
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
83+
with:
84+
fetch-depth: 0
85+
persist-credentials: false
86+
87+
- name: Fetch base branch
88+
env:
89+
BASE_REF: ${{ github.base_ref }}
90+
run: git fetch origin "$BASE_REF"
91+
92+
- name: Authenticate with Kusari
93+
run: kusari auth login --client-id="${{ secrets.KUSARI_CLIENT_ID }}" --client-secret="${{ secrets.KUSARI_CLIENT_SECRET }}"
94+
95+
- name: Run Kusari scan
96+
id: scan
97+
env:
98+
GITHUB_TOKEN: ${{ github.token }}
99+
POST_COMMENT: ${{ inputs.post_comment }}
100+
BASE_REF: ${{ github.base_ref }}
101+
run: |
102+
GITHUB_COMMENT_FLAG=""
103+
if [ "$POST_COMMENT" = "true" ]; then
104+
GITHUB_COMMENT_FLAG="--comment github"
105+
fi
106+
kusari repo scan -w --output-format sarif $GITHUB_COMMENT_FLAG . "origin/$BASE_REF" > kusari_results.sarif
107+
108+
- name: Display scan results
109+
run: |
110+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
111+
echo "KUSARI SECURITY SCAN RESULTS"
112+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
113+
echo ""
114+
COMMENT_BODY=$(jq -r '.runs[0].results[0].message.markdown // "No results found"' kusari_results.sarif)
115+
echo "$COMMENT_BODY"
116+
echo ""
117+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
118+
119+
- name: Check for security issues
120+
if: inputs.fail_on_issues
121+
run: |
122+
SHOULD_PROCEED=$(jq -r '.runs[0].results[0].properties.should_proceed // "true"' kusari_results.sarif)
123+
if [ "$SHOULD_PROCEED" = "false" ]; then
124+
echo "Security issues found - failing workflow"
125+
exit 1
126+
fi
127+
128+
- name: Upload SARIF results
129+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 #v4.6.2
130+
if: always()
131+
with:
132+
name: kusari-sarif-results
133+
path: kusari_results.sarif
134+
retention-days: 30

.github/workflows/release.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*.*.*'
7+
8+
jobs:
9+
release:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: write
13+
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
17+
with:
18+
persist-credentials: false
19+
20+
- name: Update major version tag
21+
run: |
22+
# Get the tag that triggered this workflow
23+
TAG=${GITHUB_REF#refs/tags/}
24+
25+
# Extract major version (v1 from v1.0.1)
26+
MAJOR_VERSION=$(echo "$TAG" | grep -oE '^v[0-9]+')
27+
28+
if [ -z "$MAJOR_VERSION" ]; then
29+
echo "Could not extract major version from tag: $TAG"
30+
exit 1
31+
fi
32+
33+
echo "Full tag: $TAG"
34+
echo "Major version tag: $MAJOR_VERSION"
35+
36+
# Configure git
37+
git config user.name "github-actions[bot]"
38+
git config user.email "github-actions[bot]@users.noreply.github.com"
39+
40+
# Delete the major version tag locally if it exists
41+
git tag -d "$MAJOR_VERSION" 2>/dev/null || true
42+
43+
# Create the major version tag pointing to current commit
44+
git tag "$MAJOR_VERSION"
45+
46+
# Force push the major version tag
47+
git push origin "$MAJOR_VERSION" --force
48+
49+
echo "Successfully updated $MAJOR_VERSION to point to $TAG"

README.md

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,112 @@
1-
# kusari-ci-templates
1+
# Kusari CI/CD Templates
2+
3+
Reusable CI/CD templates for integrating [Kusari Inspector](https://www.kusari.dev/inspector) security scanning into your GitLab and GitHub workflows. These templates automatically scan pull requests and merge requests for security vulnerabilities and post results as comments.
4+
5+
## Features
6+
7+
- **Automated Security Scanning**: Runs on every pull/merge request
8+
- **Auto-commenting**: Posts scan results directly to PRs/MRs when issues are found
9+
- **SARIF Output**: Generates industry-standard SARIF reports
10+
- **Configurable**: Control failure behavior and comment posting
11+
- **Zero Setup**: Just add secrets and include the template
12+
13+
## Available Templates
14+
15+
### GitLab CI/CD Template
16+
17+
Location: [`gitlab/kusari-scan-v1.yml`](gitlab/kusari-scan-v1.yml)
18+
19+
**Usage:**
20+
21+
```yaml
22+
# .gitlab-ci.yml
23+
include:
24+
- remote: 'https://raw.githubusercontent.com/kusaridev/kusari-ci-templates/v1/gitlab/kusari-scan-v1.yml'
25+
```
26+
27+
**Required Setup:**
28+
1. Add CI/CD variables in GitLab (Settings > CI/CD > Variables):
29+
- `KUSARI_CLIENT_ID`: Your Kusari client ID
30+
- `KUSARI_CLIENT_SECRET`: Your Kusari client secret (mark as masked)
31+
32+
2. For MR comments, choose one option:
33+
- **Option A (Recommended)**: Create a Project Access Token with `api` scope and add as `GITLAB_TOKEN` variable
34+
- **Option B**: Enable CI job token API access in Settings > CI/CD > Token Access
35+
36+
See [`gitlab/kusari-scan-v1.yml`](gitlab/kusari-scan-v1.yml) for detailed configuration options.
37+
38+
---
39+
40+
### GitHub Actions Reusable Workflow
41+
42+
Location: [`.github/workflows/kusari-scan-v1.yml`](.github/workflows/kusari-scan-v1.yml)
43+
44+
**Usage:**
45+
46+
Create `.github/workflows/kusari-scan.yml` in your repository:
47+
48+
```yaml
49+
name: Kusari Security Scan
50+
51+
on:
52+
pull_request:
53+
branches: [main, master]
54+
55+
jobs:
56+
kusari-scan:
57+
uses: kusaridev/kusari-ci-templates/.github/workflows/kusari-scan-v1.yml@v1
58+
permissions:
59+
contents: read
60+
pull-requests: write # Required for PR comments
61+
secrets:
62+
KUSARI_CLIENT_ID: ${{ secrets.KUSARI_CLIENT_ID }}
63+
KUSARI_CLIENT_SECRET: ${{ secrets.KUSARI_CLIENT_SECRET }}
64+
with:
65+
fail_on_issues: false # Optional: fail workflow on security issues
66+
post_comment: true # Optional: post results as PR comment
67+
```
68+
69+
**Required Setup:**
70+
1. Add repository secrets (Settings > Secrets and variables > Actions):
71+
- `KUSARI_CLIENT_ID`: Your Kusari client ID
72+
- `KUSARI_CLIENT_SECRET`: Your Kusari client secret
73+
74+
2. Ensure the workflow has `pull-requests: write` permission for commenting
75+
76+
See [`.github/workflows/kusari-scan-v1.yml`](.github/workflows/kusari-scan-v1.yml) for detailed configuration options.
77+
78+
## Configuration Options
79+
80+
| Option | GitLab | GitHub | Description | Default |
81+
|--------|--------|--------|-------------|---------|
82+
| Fail on issues | `KUSARI_FAIL_ON_ISSUES` | `fail_on_issues` | Fail pipeline/workflow when security issues found | `false` |
83+
| Post comment | `KUSARI_POST_COMMENT` | `post_comment` | Post scan results as MR/PR comment | `true` |
84+
| CLI image | `KUSARI_CLI_IMAGE` | `kusari_cli_image` | Override default Kusari CLI container image | Latest stable |
85+
86+
## Getting Kusari Credentials
87+
88+
To use these templates, you need Kusari Inspector credentials:
89+
90+
1. Sign up at [https://us.kusari.cloud/signup](https://us.kusari.cloud/signup)
91+
2. Get your `KUSARI_CLIENT_ID` and `KUSARI_CLIENT_SECRET`
92+
3. Add them to your CI/CD platform's secrets/variables
93+
94+
## Enterprise / Self-Hosted Setup
95+
96+
For air-gapped or self-hosted environments:
97+
98+
1. Mirror `ghcr.io/kusaridev/kusari-cli` to your internal container registry
99+
2. Copy the template files to your internal Git repository
100+
3. Update the `KUSARI_CLI_IMAGE` / `kusari_cli_image` to point to your internal registry
101+
4. Include/reference from your internal location
102+
103+
## Support
104+
105+
- Documentation: [https://docs.us.kusari.cloud/Inspector/](https://docs.us.kusari.cloud/Inspector/)
106+
- Website: [https://www.kusari.dev/inspector](https://www.kusari.dev/inspector)
107+
108+
## Version Tagging
109+
110+
This repository uses major version tags for easy updates:
111+
- Use `@v1` to always get the latest v1.x.x release
112+
- Use `@v1.0.1` to pin to a specific version

gitlab/kusari-scan-v1.yml

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Kusari GitLab CI/CD Template
2+
#
3+
# This template provides automated security scanning for merge requests using Kusari Inspector.
4+
# It automatically posts scan results as comments on merge requests when issues are found.
5+
#
6+
# PUBLIC GITLAB.COM USAGE:
7+
# include:
8+
# - remote: 'https://raw.githubusercontent.com/kusaridev/kusari-cli/v0.17.9/ci-templates/gitlab/kusari-scan.yml'
9+
#
10+
# ENTERPRISE/SELF-HOSTED GITLAB USAGE:
11+
# 1. Mirror ghcr.io/kusaridev/kusari-cli to your internal container registry
12+
# 2. Copy this file to your internal GitLab instance (e.g., gitlab.corp.com/platform/ci-templates)
13+
# 3. Update KUSARI_CLI_IMAGE variable to point to your internal registry
14+
# 4. Include in your projects:
15+
#
16+
# include:
17+
# - project: 'platform/ci-templates'
18+
# ref: 'main'
19+
# file: '/gitlab/kusari-scan.yml'
20+
#
21+
# REQUIRED CI/CD VARIABLES (set in GitLab project/group settings):
22+
# - KUSARI_CLIENT_ID: Your Kusari client ID
23+
# - KUSARI_CLIENT_SECRET: Your Kusari client secret (mark as masked)
24+
#
25+
# REQUIRED FOR MR COMMENTS (choose one option):
26+
# Option A - Use a GitLab Token (Recommended):
27+
# 1. Create a Project Access Token or Personal Access Token with 'api' scope
28+
# (Settings > Access Tokens > Add new token > Select 'api' scope)
29+
# 2. Add the token as a CI/CD variable named GITLAB_TOKEN (mark as masked)
30+
# (Settings > CI/CD > Variables > Add variable)
31+
#
32+
# Option B - Enable CI_JOB_TOKEN API Access:
33+
# 1. Go to Settings > CI/CD > Token Access
34+
# 2. Enable "Allow CI job tokens from this project to access this project's API"
35+
# Note: This option has more limited permissions and may not work in all scenarios
36+
#
37+
# OPTIONAL VARIABLES:
38+
# - KUSARI_CLI_IMAGE: Override the default Kusari CLI image
39+
# - KUSARI_FAIL_ON_ISSUES: Set to "true" to fail pipeline on security issues (default: "false")
40+
# - KUSARI_POST_COMMENT: Set to "true" to post results as MR comment (default: "true")
41+
42+
variables:
43+
KUSARI_CLI_IMAGE: "ghcr.io/kusaridev/kusari-cli@sha256:955262cae4d161f68cb623b273cb9a3d589004a2e7f661b15ff0d1697e494903"
44+
KUSARI_FAIL_ON_ISSUES: "false"
45+
KUSARI_POST_COMMENT: "true"
46+
47+
.kusari-scan:
48+
image:
49+
name: ${KUSARI_CLI_IMAGE}
50+
entrypoint: [""]
51+
stage: test
52+
rules:
53+
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
54+
before_script:
55+
- apk add --no-cache git jq gnutar bzip2
56+
script:
57+
- git fetch origin ${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}
58+
- kusari auth login --client-id="${KUSARI_CLIENT_ID}" --client-secret="${KUSARI_CLIENT_SECRET}"
59+
# Run scan with GitLab comment posting (if enabled)
60+
# The --comment gitlab flag will post results directly to the MR if issues are found
61+
- |
62+
GITLAB_COMMENT_FLAG=""
63+
if [ "$KUSARI_POST_COMMENT" = "true" ]; then
64+
GITLAB_COMMENT_FLAG="--comment gitlab"
65+
fi
66+
kusari repo scan -w --output-format sarif $GITLAB_COMMENT_FLAG . origin/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME} > kusari_results.sarif
67+
- |
68+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
69+
echo "KUSARI SECURITY SCAN RESULTS"
70+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
71+
echo ""
72+
COMMENT_BODY=$(jq -r '.runs[0].results[0].message.markdown // "No results found"' kusari_results.sarif)
73+
SHOULD_PROCEED=$(jq -r '.runs[0].results[0].properties.should_proceed // "true"' kusari_results.sarif)
74+
echo "$COMMENT_BODY"
75+
echo ""
76+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
77+
- |
78+
SHOULD_PROCEED=$(jq -r '.runs[0].results[0].properties.should_proceed // "true"' kusari_results.sarif)
79+
if [ "$KUSARI_FAIL_ON_ISSUES" = "true" ] && [ "$SHOULD_PROCEED" = "false" ]; then
80+
echo "Security issues found - failing pipeline"
81+
exit 1
82+
fi
83+
artifacts:
84+
reports:
85+
sast: kusari_results.sarif
86+
paths:
87+
- kusari_results.sarif
88+
expire_in: 30 days
89+
when: always
90+
91+
kusari-repo-scan:
92+
extends: .kusari-scan
93+
allow_failure: true

0 commit comments

Comments
 (0)