> For the complete documentation index, see [llms.txt](https://docs.elimity.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.elimity.com/azure-devops/step-by-step-deployment-guide.md).

# Step-by-step deployment guide

The Azure Devops connector imports users, groups, projects, repositories and user specific permissions into Elimity Insights. Read up on the specifics and how to configure this connector below!

## 1. Which data is imported from Azure Devops?

The following Azure Devops metadata is imported:

* `Users`
* `Organization Groups`&#x20;
* `Project Groups`
* `Projects`
* `User Specific Project Permissions`
* `Repositories`
* `User Specific Repository Permissions`

The diagram below gives more information on the relationships between them:

```mermaid
graph TD

%% Entities
User[User]
OrgGroup[Organization Group]
ProjGroup[Project Group]
Project[Project]
Repo[Repository]
GPP[Granted Project Permission]
GRP[Granted Repository Permission]

%% Relationships
User --> OrgGroup
User --> ProjGroup

OrgGroup --> ProjGroup

User --> GPP
User --> GRP

GPP --> Project
GRP --> Repo
```

#### User attributes

Each user entity has the following attributes:

| Attribute              | Description                                                                                                                                                                 |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `domain`               | Azure AD tenant / domain the user belongs to.                                                                                                                               |
| `mail_address`         | User's email address.                                                                                                                                                       |
| `origin`               | Identity source (e.g. `aad`, `msa`).                                                                                                                                        |
| `principal_name`       | User's UPN / login name.                                                                                                                                                    |
| `url`                  | Direct link to the user in the Azure DevOps Graph API.                                                                                                                      |
| `account_license_type` | Azure DevOps license tier assigned to the user. Possible values: `express` (Basic), `stakeholder`, `advanced` (Basic + Test Plans), `professional`, `earlyAdopter`, `none`. |

Other entities and their attributes can be inspected in the `azure-devops-data-model.json` below.

## 2. Creating a dedicated app registration in Entra ID

As usual we recommend creating a dedicated account for this connector. Follow the steps below to set up a new app registration in Entra ID:

1. In Azure, open the overview of your tenant's app registrations by typing 'app registrations' in the global search bar and clicking the 'App registrations' service.
2. Click the 'New registration' button.
3. Choose a name for this registration (e.g. `elimity-insights-azure-devops`).
4. Leave the default for 'Supported account types' and 'Redirect URI' and click 'Register'.

Note down these values:

* `Application (client) ID`
* `Directory (tenant) ID`

We'll need these later to configure the connection in Elimity.

## 3. Generating credentials for the new app registration <a href="#id-2.-generating-credentials-for-the-new-app-registration" id="id-2.-generating-credentials-for-the-new-app-registration"></a>

The Azure Devops connector authenticates as the app registration using a client secret. Click "Certificates & secrets" in the menu on the left and add a new client secret. Immediately note down the value of your new secret.&#x20;

## 4. Retrieve your Azure Devops organization name

Get your Azure Devops organization name. You can find this as part of the URL of your Azure Devops tenant:

Example:

* Azure DevOps URL: `https://dev.azure.com/your-organization`
* In this case 'organization' would be `your-organization`

## 5. Add the service principal to Azure Devops

Creating the app registration in Entra ID also creates a service principal. That service principal must be added to Azure DevOps as a user.

1. In Azure DevOps, go to "Organization Settings" → "Users" and click "Add Users"
2. Search for the service principal by the name of App Registration and add it.&#x20;
3. Set the Access level to **Basic**.&#x20;
4. Add the service principal to the **Project Collection Valid Users group** under "Organization Settings" → "Permissions" to ensure it can read all projects with its metadata.

#### 5.1 (Optional but recommended) Grant the Member Entitlement Management scope

To import the `account_license_type` attribute (user license tier), the service principal also needs the **Member Entitlement Management (read)** scope.

> Without this scope, the sync still completes successfully — license information will simply be absent from users, and the import logs will show a clear `ALERT` explaining the cause. You can skip this step and grant it later if you don't need license data right away.

To grant the scope:

1. In the Azure portal, open the App registration you created in step 2.
2. In the left menu, click **API permissions** → **Add a permission**.
3. Switch to the **APIs my organization uses** tab and search for **Azure DevOps**. Select it.
4. Choose **Delegated permissions** (or **Application permissions** if your tenant uses that pattern), then check **`vso.memberentitlementmanagement`** (read user entitlements).
5. Click **Add permissions**.
6. Back on the API permissions page, click **Grant admin consent for \[your tenant]**. A tenant admin may need to do this if you don't have permission yourself.
7. Confirm the scope shows a green ✓ "Granted for \[tenant]" status.

The next Azure DevOps sync in Elimity will then populate `account_license_type` on all licensed users.

## 6. Configure the source in Elimity Insights

* Go to 'Sources' in the left navigation bar and click 'Add Source'.
* Search for 'Custom' and click 'Set Up'
* Click 'Set Up' again and fill in the name of the Source (e.g. Azure Devops)
* Select 'Upload export file'
* Click 'Continue' and upload the following file:

{% file src="/files/z4FEQMfXOKpMoVf23o5l" %}

* Now to the 'Config' tab and click 'Edit':

<figure><img src="https://3778398128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXZQKWRGC2WaplkgjWjwZ%2Fuploads%2FWg5FRnWWT0j2sQucyihq%2Fimage.png?alt=media&amp;token=9f02f9b0-424e-47c2-b955-203555c2965e" alt=""><figcaption></figcaption></figure>

* Set 'Enable automatic imports via custom gateway' to true and fill in the Gateway URL: `https://azure-devops-gateway-1027270379075.europe-west1.run.app`

* Now we need to add some configuration values. Click 'Add configuration value' and add the following configuration values:

| Key            | Type       | Where to find it |
| -------------- | ---------- | ---------------- |
| `clientId`     | `Text`     | See step 2       |
| `clientSecret` | `Password` | See step 3       |
| `tenantId`     | `Text`     | See step 2       |
| `organization` | `Text`     | See step 4       |

* The Azure Devops connector also supports 2 configuration values which allow to exclude or include certain projects. If both configuration values have been set, `includedProjects` takes precedence:

| Key                | Type                                                                      | Description                                                    |
| ------------------ | ------------------------------------------------------------------------- | -------------------------------------------------------------- |
| `includedProjects` | <p><code>JSON</code></p><p>List of strings: \["Project1", "Project2"]</p> | The integration will only import projects listed in this list. |
| `excludedProjects` | <p><code>JSON</code></p><p>List of strings: \["ProjectX", "ProjectY"]</p> | The integration will exclude mentioned projects during import. |

Now click 'Save and run'! You can monitor the progress in the 'Logs' tab. Also the 'Imports' tab gives more information if anything went wrong.

## 7. Troubleshooting

#### `account_license_type` is missing for all users

The import logs will show an `ALERT` like:

> Failed to fetch user entitlements (continuing without `account_license_type`): 401 Unauthorized. Check that the service principal has the `vso.memberentitlementmanagement` scope.

**Fix**: grant the `vso.memberentitlementmanagement` (read) scope to the service principal in Azure (see step 5.1). On the next sync, the attribute will be populated.

#### `account_license_type` is missing for *some* users

This is expected because users without an assigned Azure DevOps license (deactivated accounts, guests, service accounts) don't appear in the entitlement API, so the attribute is simply absent for them. No action needed.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.elimity.com/azure-devops/step-by-step-deployment-guide.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
