|
1 | 1 | # GitLab Test Runner Setup |
2 | 2 |
|
| 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 | + |
3 | 12 | ## 1. Create Test Runner Repository |
4 | 13 |
|
5 | 14 | 1. Create a new project named `scan-test-runner-gitlab-ci` in your GitLab group |
|
8 | 17 |
|
9 | 18 | --- |
10 | 19 |
|
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) |
12 | 40 |
|
13 | | -1. Navigate to your group settings: |
14 | | - **Group → Settings → Applications** |
| 41 | +1. Navigate to your project: |
| 42 | + **Project → Settings → Access tokens** |
15 | 43 |
|
16 | | - Or for self-hosted: `https://{GITLAB_HOST}/groups/{GROUP}/-/settings/applications` |
| 44 | + Or: `https://gitlab.com/{GROUP}/{PROJECT}/-/settings/access_tokens` |
17 | 45 |
|
18 | | -2. Click **Add new application** |
| 46 | +2. Click **Add new token** |
19 | 47 |
|
20 | | -3. Configure the application: |
| 48 | +3. Configure the token: |
21 | 49 |
|
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 | |
28 | 56 |
|
29 | | -4. Click **Save application** |
| 57 | +4. Click **Create project access token** |
30 | 58 |
|
31 | | -5. Note the **Application ID** and **Secret** - the secret is only shown once! |
| 59 | +5. Copy the **token** - it's only shown once! |
32 | 60 |
|
33 | 61 | --- |
34 | 62 |
|
35 | | -## 3. Configure Secrets on Scanner Registry Repository |
| 63 | +## 4. Configure Secrets on Scanner Registry Repository |
36 | 64 |
|
37 | 65 | Navigate to the scanner registry repository (GitHub): |
38 | 66 | **Settings → Secrets and variables → Actions → New repository secret** |
39 | 67 |
|
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 | |
44 | 72 |
|
45 | 73 | --- |
46 | 74 |
|
47 | | -## 4. Usage in GitHub Actions Workflow |
| 75 | +## 5. Usage in GitHub Actions Workflow |
48 | 76 |
|
49 | 77 | ```yaml |
50 | | -- name: Generate GitLab OAuth Token |
51 | | - id: gitlab-token |
| 78 | +- name: Run test-action |
52 | 79 | 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 | +``` |
57 | 83 |
|
58 | | - token=$(echo "$response" | jq -r '.access_token') |
59 | | - echo "token=$token" >> $GITHUB_OUTPUT |
60 | | - echo "::add-mask::$token" |
| 84 | +--- |
61 | 85 |
|
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 | |
65 | 92 |
|
66 | 93 | --- |
67 | 94 |
|
68 | | -## 5. Token Details |
| 95 | +## 7. Security Notes |
69 | 96 |
|
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 |
75 | 101 |
|
76 | 102 | --- |
77 | 103 |
|
78 | 104 | ## References |
79 | 105 |
|
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) |
0 commit comments