> ## Documentation Index
> Fetch the complete documentation index at: https://docs.neoagent.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Connecting Microsoft Azure to Neo

> Create an app registration for Neo, give it a role limited to firewall rules, save it in Neo and turn Azure on for your agents

You connect Azure once at the MSP level, then turn it on per agent. Neo manages IP allow rules only, and it can do only what the Azure roles you give its app allow.

## 1. Create an app registration

**1. Register the app**

In the [Microsoft Entra admin center](https://entra.microsoft.com), open **Identity** > **Applications** > **App registrations** and click **New registration**. Name it "Neo", keep **Accounts in this organizational directory only**, and click **Register**.

**2. Copy the ids**

On the app's **Overview**, copy the **Directory (tenant) ID** and the **Application (client) ID**.

**3. Create a client secret**

Open **Certificates & secrets** > **Client secrets** > **New client secret**. Copy the secret's **Value** (not its Secret ID): Microsoft shows it only once. Note when it expires; Neo stops working with Azure on that date until you save a new one.

The app needs no API permissions in Entra ID. Azure Resource Manager access comes from Azure roles, in the next step.

## 2. Give the app Azure roles

In the [Azure portal](https://portal.azure.com), create a custom role with the actions below (**Subscriptions** > the subscription > **Access control (IAM)** > **Add** > **Add custom role** > **JSON**). Then assign it to the "Neo" app on each resource group (or resource) whose rules Neo should manage: **Access control (IAM)** > **Add role assignment**, pick the role, and select the app as the member.

```json theme={null}
{
  "Name": "Neo firewall rules",
  "Actions": [
    "Microsoft.Resources/subscriptions/read",
    "Microsoft.Resources/subscriptions/resources/read",
    "Microsoft.Resources/subscriptions/resourceGroups/read",
    "Microsoft.Resources/subscriptions/resourceGroups/resources/read",
    "Microsoft.Sql/servers/read",
    "Microsoft.Sql/servers/firewallRules/*",
    "Microsoft.DBforPostgreSQL/flexibleServers/read",
    "Microsoft.DBforPostgreSQL/flexibleServers/firewallRules/*",
    "Microsoft.DBforMySQL/flexibleServers/read",
    "Microsoft.DBforMySQL/flexibleServers/firewallRules/*",
    "Microsoft.KeyVault/vaults/read",
    "Microsoft.KeyVault/vaults/write",
    "Microsoft.Storage/storageAccounts/read",
    "Microsoft.Storage/storageAccounts/write",
    "Microsoft.AnalysisServices/servers/read",
    "Microsoft.AnalysisServices/servers/write"
  ],
  "AssignableScopes": ["/subscriptions/<subscription id>"]
}
```

Leave out the lines for services you do not use. The `write` actions on a vault, storage account or Analysis Services server allow other changes too, but Neo sends those resources only a change to their IP rule list and refuses every other change.

**Your clients' subscriptions:** when a client's Azure is in its own tenant, the client delegates its subscriptions (or resource groups) to your "Neo" app with [Azure Lighthouse](https://learn.microsoft.com/en-us/azure/lighthouse/overview). Lighthouse supports built-in roles only, not the custom role above, so use the narrowest built-in roles that allow rule changes, such as SQL Server Contributor, Key Vault Contributor and Storage Account Contributor, on the resource groups Neo should manage. Those roles allow more than rule changes, but Neo sends these resources only IP rule changes. Microsoft Azure takes no client-owned app: every call runs as your app, inside the subscriptions mapped to the ticket's company.

> [!NOTE]
>
> A new role assignment can take a few minutes to apply. If Neo says the app has no role on any subscription, wait and save again.

## 3. Add the credential in Neo

**1. Open Integrations**

In the Neo Dashboard, open **Integrations** and find the Microsoft Azure card, under Servers & Virtualization.

**2. Save the credential**

Paste the Directory (tenant) ID, the Application (client) ID and the client secret, and click **Save**. Neo signs in to Microsoft with them and lists the subscriptions the app can see before it saves, so a wrong value, or an app with no role yet, is rejected straight away with the reason. The **Organization Mapping** tab fills after the save, and again on each nightly PSA sync.

## 4. Turn Azure on per agent

Open the agent, go to its **Tools & Settings** tab, click **Servers & Virtualization**, and expand the **Microsoft Azure** block. It has one area, **IP Allow Rules**: **Read Only** finds resources and reads their rules, **Read / Write** also adds and removes rules. Turn on **Require approval** to have a technician approve each change. A change whose rules allow more than 256 addresses together (more than a `/24`), or a rule that holds `0.0.0.0`, always waits for a technician's approval.

Neo never reads anything else through Azure, and the agent sees only the fields this job needs: names, types, rules and their state.

## Example: allow a ticket's IP addresses on several resources

Give an agent that runs on your "IP allowlist" tickets **IP Allow Rules** on Read / Write, and instructions like these:

> For each IP address in the ticket, allow it on the Azure resources sql-app-dev, kv-app-dev and aas-app-dev. Keep every rule already there. Then check each address is allowed on every resource, and add a note listing each resource and address and whether it was already allowed or added.

Turn on **Require approval** on IP Allow Rules while you watch the first runs; each change then waits for a technician.

To have Neo do more in Azure, [request an integration](https://docs.neoagent.io/integrations/request-an-integration.md).

## Troubleshooting

| Error on save | Fix |
| - | - |
| Microsoft refused the client secret | Create a new client secret and paste its **Value**, not its Secret ID. |
| No application with that Application (client) ID | Check the ids are from the same app registration, in the tenant you entered. |
| The app has no role on any Azure subscription | Assign it a role on a subscription or resource (step 2), wait a few minutes and save again. |
| A call fails with AuthorizationFailed | The app's roles do not allow that action on that resource. Add the role the error names. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.