Skip to content
Open
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
90 changes: 71 additions & 19 deletions docs/integrations/azure-devops-ast-orchestrator.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
id: azure-devops-ast-orchestrator
title: Azure DevOps AST Orchestrator
sidebar_label: AST Orchestrator
description: Configure a centralized Azure DevOps pipeline to run Conviso AST after PR merges using only CONVISO_API_KEY.
description: Configure a centralized Azure DevOps pipeline to run Conviso AST after PR merges on every branch matching your AST branch pattern, using only CONVISO_API_KEY.
keywords:
[
Azure DevOps AST Orchestrator,
Application Security Testing,
Azure Pipelines,
pipeline-orchestrator,
AST branch pattern,
multi-branch AST,
conviso-ast-repository-token,
Conviso Platform,
]
Expand Down Expand Up @@ -38,7 +40,7 @@ What Conviso checks before dispatching:
1. The event is a pull request that was **merged**.
2. **AST scans on merge** is enabled on the Azure DevOps integration.
3. The repository is an **imported asset** that is **enabled**.
4. The PR **destination branch** matches the configured merge target (see [Merge target branch](#merge-target-branch) below).
4. The PR **destination branch** matches the configured [AST branch pattern](#ast-branch-pattern).

The pipeline always appears on the **orchestrator** project (not on the application repository).

Expand Down Expand Up @@ -66,23 +68,65 @@ You need:
| **Orchestrator pipeline** | Azure Pipeline whose YAML is `azure-pipelines.yml`. Conviso triggers this pipeline only. |
| **Target repository** | Application repo imported as an asset. It must **not** rely on a local Conviso pipeline for this flow. |
| **Ref** | Branch or tag **of the orchestrator** where Azure loads `azure-pipelines.yml` when Conviso starts the run. |
| **Merge target branch** | The PR **destination** branch on the **target** repo that is allowed to trigger a scan (for example `main`). See below. |
| **AST branch pattern** | Regular expression matched against the merged PR's **destination** branch on the **target** repo. Only a branch it matches triggers a scan. See below. |
| **Asset** | Imported repository in Conviso where findings are stored. |

### Merge target branch
### AST branch pattern

Conviso compares the merged PR’s **destination branch** to:
Conviso decides whether a merge triggers a scan by matching the merged PR's **destination branch**
against a **regular expression** you configure — the **AST branch pattern**. One pattern can name
several branches (`main|develop`) or a whole family of them (`release/.*`).

1. The asset’s configured AST / branch mapping, if set; otherwise
2. The integration **Ref** (`orchestrator_ref`).
Before this, the platform compared that branch to a **single name**, with exact equality. Only two
setups were expressible: one branch, or every branch.

| Configuration | What triggers a scan |
#### Where you set it

| Level | Where | Applies to |
| --- | --- | --- |
| **Repository** | The **Branch pattern** column on the repository table, in the integration's configuration step | That repository only |
| **Integration** | **Branch pattern that runs the AST**, on the integration configuration page | Every repository of this integration that has no pattern of its own |

#### Which one applies

The first level that is configured wins:

1. The repository's own **Branch pattern**.
2. The integration's **Branch pattern that runs the AST**.
3. The integration **Ref** — *legacy fallback*, so nothing changes for a setup that was already using Ref as a branch filter.
4. Nothing configured — **every branch** triggers a scan.

:::note Ref is the orchestrator's branch, not a branch policy
**Ref** means "which branch of the orchestrator project holds `azure-pipelines.yml`". It was reused as a branch
filter before the branch pattern existed, and it still is when nothing else is set — but it is no
longer the field to use for branch policy. Set a branch pattern instead, and leave Ref meaning the
one thing it should mean.
:::

#### How a pattern is matched

* **The whole branch name must match.** `main` matches `main` and nothing else — not `maintenance`, not `remain`.
* **A plain branch name behaves exactly as it did before.** Every value already configured in your account keeps meaning exactly what it means today. There is nothing to migrate and nothing you need to do.
* **`|` is how you list branches:** `main|develop|homolog`.
* **The pattern is validated when you save it.** One that does not compile, is longer than 500 characters, or is too slow to evaluate is refused, with the reason shown under the field.
* **A pattern that fails at merge time does not dispatch.** If a stored expression errors or times out while a merge is being evaluated, Conviso skips the scan rather than spending your CI budget on a decision it could not make.

#### Examples

| Pattern | Merges that trigger a scan |
| --- | --- |
| Asset branch = `master`, Ref = `main` | Only merges **into `master`** on that asset |
| Asset branch empty, Ref = `main` | Only merges **into `main`** on that asset |
| Asset branch empty and Ref empty | No branch filter (any destination branch can trigger). Prefer setting Ref explicitly. |
| *(nothing set at any level)* | Every branch |
| `main` | `main` only |
| `main\|develop` | `main` and `develop` |
| `release/.*` | Every branch under `release/` |
| `main\|release/.*` | `main`, and every branch under `release/` |
| `main` *(stored before this feature)* | `main` only — unchanged |

#### Running the AST on demand

**Ref is still the orchestrator branch that holds `azure-pipelines.yml`.** It is reused as the default merge-target filter when the asset has no branch of its own. Those are two roles of the same field — do not confuse “where the YAML lives” with “any branch on the target”.
**Run AST** on the asset offers a **Branch to scan** picker, listing only the branches that match
that asset's pattern. If the pattern matches none of the asset's branches, the button is disabled
and says so — adjust the pattern in the integration settings.

---

Expand Down Expand Up @@ -368,22 +412,26 @@ Do **not** add an Azure DevOps PAT for clone. The job calls `conviso-ast-reposit
| **Orchestrator project** | Project that contains the orchestrator pipeline | Second path segment of the same URL |
| **Orchestrator pipeline ID** | The number from Step 3, e.g. `42` | `definitionId=` in the pipeline URL |
| **Orchestrator ref** | Branch holding the YAML — usually `main` | Same branch from Step 1. Conviso prefixes plain values with `refs/heads/`; a tag must be written as `refs/tags/<tag>` |
| **Branch pattern that runs the AST** | Optional regular expression for the branches on the **target** repositories that should trigger a scan, e.g. `main\|develop` | Leave empty to keep using **Orchestrator ref** as the filter. See [AST branch pattern](#ast-branch-pattern) |

4. Save.

![Step 5: Orchestrator configuration in Conviso](/img/azure-devops/ast-step-02-orchestrator-config.png)

### Step 6 – Assets and merge target
### Step 6 – Assets and branch pattern

1. Confirm each application repository is **imported** and **enabled**.
2. Set the asset branch mapping when the merge target is **not** the same as Ref (example: Ref `main` on the orchestrator, merges into `master` on the asset → map the asset to `master`).
3. If the asset has no branch mapping, merges must go into the branch named by **Ref** (or any branch only if Ref is also empty — avoid that setup).
2. Set **Branch pattern that runs the AST** on the integration page when more than one branch should be scanned — `main|develop`, or `release/.*`.
3. Override it for a single repository from the **Branch pattern** column on the repository table, when that one ships from a different branch than the rest.
4. If you set neither, the integration **Ref** is still used as the filter (legacy behavior); if Ref is empty too, every branch triggers a scan.

See [AST branch pattern](#ast-branch-pattern) for how the expression is matched and validated.

---

## End-to-end flow (after setup)

1. Developer merges a PR into the configured merge target on an imported, enabled asset.
1. Developer merges a PR into a branch matching the AST branch pattern, on an imported, enabled asset.
2. Conviso validates the event and configuration, then starts the orchestrator pipeline on the **Ref** branch.
3. Template parameters include the repository, branch, and related ids Conviso needs for the run.
4. Job steps: issue repository token → clone target → run `conviso-ast` → upload session artifact.
Expand All @@ -397,7 +445,7 @@ Do **not** add an Azure DevOps PAT for clone. The job calls `conviso-ast-reposit
| Variable | `CONVISO_API_KEY` exists as a **secret pipeline variable** on the orchestrator |
| Path | `azure-pipelines.yml` is on the **Ref** branch |
| Conviso | Organization + project + pipeline ID + Ref saved; **AST scans on merge** on |
| Asset | Target repo imported, enabled; merge target branch matches mapping or Ref |
| Asset | Target repo imported, enabled; the merged branch matches the AST branch pattern (repository level, integration level, or Ref as the legacy fallback) |
| After merge | New pipeline run on the orchestrator; findings (or a clean result) on the asset |

![Validation: successful orchestrator pipeline run](/img/azure-devops/ast-step-06-run-success.png)
Expand All @@ -408,13 +456,17 @@ Manual test (optional): on the orchestrator, **Run pipeline**. Set `repo_full_na

| Symptom | Cause / fix |
|---------|-------------|
| Merge done, no pipeline | **AST scans on merge** off; organization/project/pipeline ID/Ref incomplete; asset disabled or not imported; PR destination ≠ asset branch / Ref; connecting user lacks **Edit subscriptions** so no Service Hook was registered ([details](./azure-devops.md#service-hook-permissions)) |
| Merge done, no pipeline | **AST scans on merge** off; organization/project/pipeline ID/Ref incomplete; asset disabled or not imported; the merged branch does not match the AST branch pattern; connecting user lacks **Edit subscriptions** so no Service Hook was registered ([details](./azure-devops.md#service-hook-permissions)) |
| A branch you expected to scan is skipped | The pattern does not match the whole branch name. `main` does not match `main-hotfix`; use `main.*` if that is what you meant. Check the repository pattern first — it overrides the integration's |
| No branch scans any more, after editing a pattern | A stored pattern that fails to compile or times out is treated as "do not dispatch". Reopen the field, save a valid expression, and confirm it is accepted |
| The pattern is refused when you save it | It does not compile, is longer than 500 characters, or is too slow to evaluate. The reason is shown under the field |
| **Run AST** is disabled on the asset | The pattern matches none of the asset's branches. Adjust it in the integration settings |
| `Repository is not available for this API key` | Wrong environment (`CONVISO_API_KEY` vs `api_url`); Azure integration not authorized; asset not imported/enabled for that company |
| Unreadable / HTML response from Platform | Use the production API host (`https://api.convisoappsec.com`). The template remaps `https://app.convisoappsec.com` automatically |
| Initialize containers fails | Confirm `options: --entrypoint ""` is present on the container |
| `CONVISO_API_KEY` empty / unauthorized | Confirm the secret is a **pipeline variable** (Edit → Variables). A Library / variable group is not enough unless the YAML also references that group — this template does not |
| Scanner missing `CONVISO_COMPANY_ID` | Manual run without `company_id` and without pipeline variable `CONVISO_COMPANY_ID` |
| Wrong code scanned | Merge target / `branch` mismatch; confirm you merged into the configured destination branch |
| Wrong code scanned | `branch` mismatch; confirm you merged into a branch the AST branch pattern matches |

## Migrating from `System.AccessToken` or `ADO_GIT_PAT`

Expand Down
Loading