Skip to content

Commit 43bcb5a

Browse files
authored
BST-18006 Add the gitlab-ci scan tests (#268)
1 parent e9c136a commit 43bcb5a

File tree

5 files changed

+122
-61
lines changed

5 files changed

+122
-61
lines changed

.github/workflows/scan-test.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,24 @@ jobs:
6767
}
6868
registry-repo: "${{ github.repository_owner }}/${{ github.event.repository.name }}"
6969
base-ref: "${{ github.base_ref }}"
70+
71+
gitlab-ci:
72+
name: Gitlab-CI
73+
runs-on: ubuntu-latest
74+
steps:
75+
- name: Checkout scanner registry
76+
uses: actions/checkout@v4
77+
with:
78+
fetch-depth: 0 # Need full history to detect changes
79+
- name: Run Tests
80+
uses: boostsecurityio/scan-test-action@53e2f687ab93ac5d150b88abd7341b72f6fbf384
81+
with:
82+
provider: gitlab-ci
83+
provider-config: |
84+
{
85+
"trigger_token": "${{ secrets.BOOST_SCAN_RUNNER_GITLAB_TRIGGER_TOKEN }}",
86+
"api_token": "${{ secrets.BOOST_SCAN_RUNNER_GITLAB_READ_TOKEN }}",
87+
"project_id": "boostsecurityio/scan-test-runner-gitlab-ci"
88+
}
89+
registry-repo: "${{ github.repository_owner }}/${{ github.event.repository.name }}"
90+
base-ref: "${{ github.base_ref }}"

docs/authentication-strategy.md

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ Migration from long-lived user tokens to short-lived OAuth2/OIDC tokens across a
88

99
## Authentication Solution
1010

11-
| Platform | Auth Method | Token Lifetime | User-Independent |
12-
|------------------|---------------------------|----------------|------------------|
13-
| **GitHub** | GitHub App | 1 hour ||
14-
| **GitLab** | OAuth2 Application | 2 hours | |
15-
| **Azure DevOps** | OIDC (Federated Identity) | ~1 hour ||
16-
| **Bitbucket** | OAuth2 Consumer | 2 hours ||
11+
| Platform | Auth Method | Token Lifetime | User-Independent |
12+
|------------------|--------------------------------------|-----------------------|------------------|
13+
| **GitHub** | GitHub App | 1 hour ||
14+
| **GitLab** | Trigger Token + Read Token (2-token) | Trigger: ∞, Read: 1yr | ⚠️ Read token |
15+
| **Azure DevOps** | OIDC (Federated Identity) | ~1 hour ||
16+
| **Bitbucket** | OAuth2 Consumer | 2 hours ||
1717

1818
### Architecture Flow
1919

@@ -25,7 +25,7 @@ GitHub Actions Workflow Triggered
2525
┌────────────────────────────────────┐
2626
│ Token Generation (in GH Actions) │
2727
│ - GitHub: Official Action │
28-
│ - GitLab: OAuth2 API call
28+
│ - GitLab: Stored tokens (2-token)
2929
│ - Azure: OIDC (no secrets) │
3030
│ - Bitbucket: OAuth2 API call │
3131
└────────────────────────────────────┘
@@ -39,6 +39,17 @@ Trigger test pipelines on each platform
3939
Tokens expire automatically
4040
```
4141

42+
### GitLab Two-Token Approach
43+
44+
GitLab does not support OAuth2 client credentials flow. We use two purpose-specific tokens:
45+
46+
| Token | Purpose | Scope |
47+
|----------------------------|-------------------|---------------------------------|
48+
| **Pipeline Trigger Token** | Trigger pipelines | Can only trigger, no API access |
49+
| **Project Access Token** | Poll status | `read_api` only, Guest role |
50+
51+
This provides least-privilege access - neither token alone can both trigger and read.
52+
4253
### Key Security Improvements
4354

4455
-**Short-lived tokens** - Auto-expire in 1-2 hours (vs. indefinite)
@@ -61,30 +72,32 @@ Tokens expire automatically
6172

6273
**OIDC for GitHub API** - OIDC is for external services authenticating to GitHub, not for GitHub Actions triggering other GitHub workflows; GitHub Apps are the correct solution.
6374

75+
**GitLab OAuth2 Client Credentials** - GitLab does not support OAuth2 client credentials flow for machine-to-machine authentication; two-token approach (trigger + read) provides equivalent security with least-privilege separation.
76+
6477
---
6578

6679
## Implementation Requirements
6780

6881
### One-Time Setup (per platform)
6982

7083
1. **GitHub**: Register GitHub App with `contents: read`, `actions: write` permissions
71-
2. **GitLab**: Create OAuth2 Application with `api` scope
84+
2. **GitLab**: Create Pipeline Trigger Token + Project Access Token (`read_api`, Guest role)
7285
3. **Azure DevOps**: Register Microsoft Entra ID application, add federated credential for GitHub Actions OIDC, grant Build (Read & Execute) to Azure DevOps project
7386
4. **Bitbucket**: Create OAuth2 Consumer with `pipeline`, `pipeline:write`, `repository` scopes
7487

7588
### Secrets Configuration
7689

77-
Store client credentials in GitHub Actions repository secrets:
78-
- `GH_APP_ID`, `GH_APP_PRIVATE_KEY`
79-
- `GITLAB_CLIENT_ID`, `GITLAB_CLIENT_SECRET`
80-
- `AZURE_TENANT_ID`, `AZURE_CLIENT_ID` (no client secret - uses OIDC; no subscription needed for Azure DevOps API)
81-
- `BITBUCKET_CLIENT_ID`, `BITBUCKET_CLIENT_SECRET`
90+
Store credentials in GitHub Actions repository secrets:
91+
- `BOOST_SCAN_RUNNER_GITHUB_APP_ID`, `BOOST_SCAN_RUNNER_GITHUB_APP_PRIVATE_KEY`
92+
- `BOOST_SCAN_RUNNER_GITLAB_TRIGGER_TOKEN`, `BOOST_SCAN_RUNNER_GITLAB_READ_TOKEN`
93+
- `BOOST_SCAN_RUNNER_ADO_TENANT_ID`, `BOOST_SCAN_RUNNER_ADO_CLIENT_ID` (no client secret - uses OIDC)
94+
- `BOOST_SCAN_RUNNER_BITBUCKET_CLIENT_ID`, `BOOST_SCAN_RUNNER_BITBUCKET_CLIENT_SECRET`
8295

8396
### Code Changes
8497

8598
- **GitHub Actions workflow**: Add token generation steps (GitHub App action, OAuth API calls, azure/login with OIDC)
8699
- **GitHub Actions permissions**: Add `id-token: write` permission for Azure OIDC
87-
- **test-action CLI**: Accept `--{platform}-token` arguments instead of client credentials
100+
- **test-action CLI**: Accept `--{platform}-token` arguments (GitLab: `--gitlab-trigger-token`, `--gitlab-read-token`)
88101
- **Providers**: Use provided tokens directly instead of generating them
89102

90103
---

docs/setup-gitlab.md

Lines changed: 68 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# GitLab Test Runner Setup
22

3+
GitLab does not support OAuth2 client credentials flow. Instead, we use a **two-token approach** for least-privilege access:
4+
5+
| Token | Purpose | Permissions |
6+
|----------------------------|----------------------|------------------------------|
7+
| **Pipeline Trigger Token** | Trigger pipelines | Trigger only (no API access) |
8+
| **Project Access Token** | Poll pipeline status | `read_api` scope, Guest role |
9+
10+
---
11+
312
## 1. Create Test Runner Repository
413

514
1. Create a new project named `scan-test-runner-gitlab-ci` in your GitLab group
@@ -8,75 +17,93 @@
817

918
---
1019

11-
## 2. Create OAuth2 Application
20+
## 2. Create Pipeline Trigger Token
21+
22+
1. Navigate to your project:
23+
**Project → Settings → CI/CD → Pipeline trigger tokens**
24+
25+
Or: `https://gitlab.com/{GROUP}/{PROJECT}/-/settings/ci_cd#js-pipeline-triggers`
26+
27+
2. Click **Add new token**
28+
29+
3. Enter a description: `Scanner Registry Test Orchestrator`
30+
31+
4. Click **Create pipeline trigger token**
32+
33+
5. Copy the **trigger token** - it's only shown once!
34+
35+
6. Ensure the ** CI/CD > Variables > Minimum role to use pipeline variables ** is set to **Developer**
36+
37+
---
38+
39+
## 3. Create Project Access Token (for polling)
1240

13-
1. Navigate to your group settings:
14-
**Group → Settings → Applications**
41+
1. Navigate to your project:
42+
**Project → Settings → Access tokens**
1543

16-
Or for self-hosted: `https://{GITLAB_HOST}/groups/{GROUP}/-/settings/applications`
44+
Or: `https://gitlab.com/{GROUP}/{PROJECT}/-/settings/access_tokens`
1745

18-
2. Click **Add new application**
46+
2. Click **Add new token**
1947

20-
3. Configure the application:
48+
3. Configure the token:
2149

22-
| Field | Value |
23-
|------------------|------------------------------------------------------|
24-
| **Name** | `BoostSecurity.io Scan Test Runner` |
25-
| **Redirect URI** | `http://localhost` (not used for client credentials) |
26-
| **Confidential** | ✅ Checked |
27-
| **Scopes** |`api` |
50+
| Field | Value |
51+
|---------------------|------------------------------------------------|
52+
| **Token name** | `Scanner Registry Status Poller` |
53+
| **Expiration date** | Set to 1 year (maximum), add rotation reminder |
54+
| **Role** | **Guest** (minimal) |
55+
| **Scopes** |`read_api` only |
2856

29-
4. Click **Save application**
57+
4. Click **Create project access token**
3058

31-
5. Note the **Application ID** and **Secret** - the secret is only shown once!
59+
5. Copy the **token** - it's only shown once!
3260

3361
---
3462

35-
## 3. Configure Secrets on Scanner Registry Repository
63+
## 4. Configure Secrets on Scanner Registry Repository
3664

3765
Navigate to the scanner registry repository (GitHub):
3866
**Settings → Secrets and variables → Actions → New repository secret**
3967

40-
| Secret Name | Value |
41-
|------------------------------------------|----------------------------|
42-
| `BOOST_SCAN_RUNNER_GITLAB_CLIENT_ID` | Application ID from step 2 |
43-
| `BOOST_SCAN_RUNNER_GITLAB_CLIENT_SECRET` | Secret from step 2 |
68+
| Secret Name | Value |
69+
|-----------------------------------------|------------------------------------|
70+
| `BOOST_SCAN_RUNNER_GITLAB_TRIGGER_TOKEN` | Pipeline trigger token from step 2 |
71+
| `BOOST_SCAN_RUNNER_GITLAB_READ_TOKEN` | Project access token from step 3 |
4472

4573
---
4674

47-
## 4. Usage in GitHub Actions Workflow
75+
## 5. Usage in GitHub Actions Workflow
4876

4977
```yaml
50-
- name: Generate GitLab OAuth Token
51-
id: gitlab-token
78+
- name: Run test-action
5279
run: |
53-
response=$(curl -s -X POST "https://gitlab.com/oauth/token" \
54-
-d "grant_type=client_credentials" \
55-
-d "client_id=${{ secrets.GITLAB_CLIENT_ID }}" \
56-
-d "client_secret=${{ secrets.GITLAB_CLIENT_SECRET }}")
80+
use "${{ secrets.BOOST_SCAN_RUNNER_GITLAB_TRIGGER_TOKEN }}" \
81+
use "${{ secrets.BOOST_SCAN_RUNNER_GITLAB_READ_TOKEN }}"
82+
```
5783
58-
token=$(echo "$response" | jq -r '.access_token')
59-
echo "token=$token" >> $GITHUB_OUTPUT
60-
echo "::add-mask::$token"
84+
---
6185
62-
- name: Run test-action
63-
...
64-
```
86+
## 6. Token Details
87+
88+
| Token | Lifetime | Scope | Rotation |
89+
|-------------------|---------------|------------------------|--------------------------------|
90+
| **Trigger Token** | No expiration | Trigger pipelines only | Manual (revoke if compromised) |
91+
| **Read Token** | 1 year max | `read_api` (read-only) | Annual rotation required |
6592

6693
---
6794

68-
## 5. Token Details
95+
## 7. Security Notes
6996

70-
| Property | Value |
71-
|--------------|--------------------------------------------------|
72-
| **Lifetime** | 2 hours |
73-
| **Refresh** | New token generated per workflow run |
74-
| **Scope** | `api` (required for pipeline trigger and status) |
97+
- **Trigger token** can only start pipelines - cannot read data or modify anything
98+
- **Read token** has Guest role with `read_api` - cannot trigger or modify anything
99+
- Neither token can access code, settings, or other projects
100+
- Separation ensures compromise of one token limits blast radius
75101

76102
---
77103

78104
## References
79105

80-
- [GitLab OAuth2 Provider](https://docs.gitlab.com/ee/integration/oauth_provider.html)
81-
- [GitLab OAuth2 API](https://docs.gitlab.com/ee/api/oauth2.html#client-credentials-flow)
82-
- [GitLab Pipelines API](https://docs.gitlab.com/ee/api/pipelines.html)
106+
- [Pipeline Trigger Tokens](https://docs.gitlab.com/ee/ci/triggers/)
107+
- [Project Access Tokens](https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html)
108+
- [GitLab API Authentication](https://docs.gitlab.com/ee/api/rest/#authentication)
109+
- [Pipelines API](https://docs.gitlab.com/ee/api/pipelines.html)
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
version: "1.0"
22
tests:
3-
- name: "gitleaks"
4-
type: "source-code"
5-
source:
6-
url: "git@github.com:gitleaks/gitleaks.git"
7-
ref: "v8.15.2"
83
- name: "osv-scanner"
94
type: "source-code"
105
source:
116
url: "git@github.com:google/osv-scanner.git"
127
ref: "main"
8+
- name: "gitleaks"
9+
type: "source-code"
10+
source:
11+
url: "git@github.com:gitleaks/gitleaks.git"
12+
ref: "v8.15.2"

scanners/boostsecurityio/trivy-image/tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ tests:
66
url: "https://github.com/martin-boost-dev/boost-poc-registry-testing-trivy"
77
ref: "main"
88
scan_paths:
9-
- "rclone"
109
- "osv-scanner"
10+
- "rclone"

0 commit comments

Comments
 (0)