Usa i connettori gestiti in Funzioni di Azure

Utilizzando connettori gestiti, le tue funzioni possono reagire a eventi e operazioni di chiamata in servizi come Microsoft 365, Microsoft Teams, SharePoint e molti sistemi di terze parti senza scrivere codice di configurazione webhook o gestire token OAuth. Funzioni di Azure si integra con Azure Connector Namespace per fornire un trigger e un SDK che consente di concentrarsi sulla logica di business, mentre Azure Connector Namespace gestisce webhook, autenticazione e nuovi tentativi.

Note

L'integrazione di Azure Connector Namespace per Funzioni di Azure è attualmente in anteprima pubblica. Caratteristiche, nomi di configurazione e supporto per specifici connettori gestiti possono cambiare prima della disponibilità generale (GA). L'utilizzo di questa funzionalità è soggetto alle condizioni d'uso supplementari per le versioni di anteprima di Microsoft Azure.

Attualmente sono supportati solo gli stack di linguaggio C#, Node.jse Python.

Come i connettori migliorano le funzioni

Uno spazio di nomi di connettori aggiunge due funzionalità al modello di programmazione delle funzioni:

  • Attivatori del connettore
    Una funzione viene eseguita quando un evento si verifica in un servizio esterno, come una nuova email in Microsoft 365, un file aggiunto a SharePoint o un messaggio pubblicato su Teams. Il runtime espone un binding connectorTrigger che riceve le callback dei webhook provenienti dal namespace del connettore.
  • Azioni del Connector SDK
    Il tuo codice di funzione chiama le operazioni dei connettori tramite client SDK. L'SDK copre connettori gestiti come Microsoft 365 Outlook, Microsoft 365 Users, Teams, SharePoint e OneDrive. I connettori gestiti che non hanno ancora modelli SDK sono chiamabili come endpoint HTTP.

Puoi utilizzare connettori gestiti insieme ai classici trigger e binding Functions come HTTP, timer, queue, bus di servizio, Event Grid e Durable Functions.

Disponibilità dell'anteprima

Dimension Availability
Regione di namespace dei connettori Centro-ovest degli Stati Uniti (westcentralus).
L'app per le funzioni può trovarsi in qualsiasi area geografica supportata.
Lingue .NET 10/.NET 8 isolato, Python 3.13+, Node.js 22+ (JS/TS). Java, PowerShell e Go non sono supportati.
Piani di hosting Flex Consumption (consigliato), Premium, Dedicated, e Container Apps.
Prezzi Prezzi di funzioni standard: Nessun costo extra per il trigger/SDK del connettore in anteprima.
Il namespace del connettore prevede una fatturazione separata.

Quando usare i connettori

Usa i connettori quando le tue funzioni devono principalmente interagire con servizi esterni piuttosto che eseguire una logica personalizzata complessa. Considera questi modi per usare i connettori gestiti nelle tue app funzionali:

  • Reagire agli eventi esterni
    La tua app deve gestire eventi generati da servizi esterni (nuove email, inviti al calendario, file, elementi di lista, attività di Teams), ma non vuoi spendere la fatica a codificare registrazioni webhook, validazione di handshake e aggiornamenti OAuth. Consideriamo un caso in cui la tua funzione viene eseguita per processare le nuove email consegnate in una cartella Office 365 Outlook monitorata, classifica il messaggio, chiama il connettore di Office 365 per l'arricchimento e segnala o sposta l'email. Tutto questo lavoro distribuito viene svolto dalla tua app senza doverti mai preoccupare dei token di refresh, che sono gestiti dal tuo namespace dei connettori.

  • Sostituire i client di servizio personalizzati
    Il tuo codice di funzione chiama già Microsoft 365 o API di terze parti usando client HTTP personalizzati, il che richiede di gestire segreti, scope e politiche di ritentazione su molte connessioni, il che può rapidamente diventare un onere di manutenzione. Puoi invece usare i client tipizzati negli SDK dei connettori direttamente nel tuo codice di funzione e lasciare che i connettori gestiti gestiscano le connessioni da soli.

  • Sfrutta una distribuzione di un'app esistente
    Hai già costruito un progetto di app a funzioni guidate dagli eventi con una pipeline di distribuzione e strumenti di monitoraggio. Puoi usare i connettori gestiti per aggiungere una nuova funzione esterna basata su trigger nello stesso progetto e sfruttare l'infrastruttura esistente. Ad esempio, un'app per funzioni che prima si basava su code di messaggi o su Logic Apps ora può reagire direttamente all'attività di Teams e collegarsi a Office 365 per verifiche interne all'organizzazione e per la ricerca dei responsabili.

  • Flussi di lavoro agentici
    Stai costruendo flussi di lavoro in cui una funzione riceve un evento, ragiona con un modello di IA e poi agisce di nuovo in un servizio esterno tramite un'operazione di connettore. È possibile sfruttare il runtime degli agenti serverless per programmare il flusso di lavoro agentico, sfruttando comunque i trigger basati su connettori gestiti e gli SDK dei connettori gestiti.

  • Controllo code-first con integrazione gestita
    Vuoi che i connettori gestiti semplifichino la comunicazione in entrata e in uscita con servizi esterni, ma preferisci un modello di programmazione basato sul codice e il pieno controllo dell'orchestrazione, inclusi i ramificazioni, la gestione dell'autenticazione tra i passaggi e il riutilizzo delle librerie esistenti.

    Tip

    Quando il carico di lavoro è pura orchestrazione tra connettori senza codice personalizzato, Logic Apps Standard rimane la scelta più semplice. Per maggiori informazioni, vedi Relazione con altre opzioni di integrazione Azure.

Relazione con altre opzioni di integrazione Azure

I connettori gestiti in Funzioni di Azure sono additivi. La scelta giusta dipende da quanta quantità di codice personalizzato serve al carico di lavoro e se il team preferisce un visual designer o un codice.

Option Ideale per... Offre...
Logic Apps Standard Orchestrare un flusso di lavoro tra i connettori; Team preferisce un visual designer; Poco codice personalizzato tra un passaggio e l'altro. Progettista con poco codice per lo stesso ecosistema di connettori.
Funzioni di Azure con connettori gestiti Esperienze di code-first che includono ramificazioni personalizzate, librerie in process, altri binding e chiamate a modelli di IA tra trigger e azione. Creazione con .NET, Python o Node.js; distribuzione e monitoraggio di Funzioni; senza codice per webhook o OAuth per servizi esterni.
HTTP si attiva con gli SDK di servizio Casi in cui non esiste un connettore gestito per il servizio bersaglio o si richiedono controlli a livello di protocollo che non sono forniti dal connettore. Controllo completo su autenticazione, ritenti e validazione del webhook; Nessun requisito per un namespace dei connettori.

Una singola app per le funzioni può combinare tutti e tre i modelli. È possibile aggiungere un trigger del connettore a un'app HTTP-trigger esistente e adottare i client SDK in modo incrementale.

Pacchetti e prerequisiti

Ogni linguaggio supportato dispone di un piccolo insieme di pacchetti che includono il trigger binding e i client SDK del connettore.

Il pacchetto di estensione del worker invia il binding del trigger del connettore. I Azure.Connectors.Sdk.* pacchetti (uno per connettore) trasportano payload e client SDK tipizzati.

dotnet add package Microsoft.Azure.Functions.Worker.Extensions.Connector --prerelease
dotnet add package Azure.Connectors.Sdk --prerelease

Per il worker isolato di .NET, usare come destinazione net8.0 o net10.0 e la versione più recente del worker di funzioni.

Python usa il pacchetto di estensioni in anteprima per caricare il binding del trigger e il pacchetto azurefunctions-extensions-connectors per i modelli Office 365 tipizzati. Aggiungere il bundle a host.json:

{
    "version": "2.0",
    "extensionBundle": {
        "id": "Microsoft.Azure.Functions.ExtensionBundle.Preview",
        "version": "[4.42.0, 5.0.0)"
    }
}

Installare i pacchetti di runtime ed estensione:

pip install "azure-functions>=2.2.0b4"
pip install azurefunctions-extensions-connectors

Il decoratore @app.connector_trigger funziona per tutti i tipi di connettori gestiti. I modelli di payload tipizzati vengono sviluppati e aggiunti attivamente tramite il azurefunctions-extensions-connectors pacchetto. Per connettori gestiti senza modelli tipizzati, si tratta il payload come una stringa.

Node.js usa il pacchetto di estensioni sperimentale per caricare il binding del trigger. Aggiungere il bundle a host.json:

{
    "version": "2.0",
    "extensionBundle": {
        "id": "Microsoft.Azure.Functions.ExtensionBundle.Preview",
        "version": "[4.42.0, 5.0.0)"
    }
}

Installare la libreria di Funzioni e i pacchetti del connettore:

npm install @azure/functions
npm install @azure/functions-extensions-connectors
npm install @azure/connectors

Usa i punti di ingresso digitati in @azure/functions-extensions-connectors (ad esempio, connectors.office365.onNewEmail) quando esistono modelli tipizzati. Usa app.connectorTrigger da @azure/functions per qualsiasi connettore gestito quando vuoi il payload grezzo.

Java e PowerShell non sono supportati nell'anteprima pubblica. Vedi Disponibilità Anteprima per l'elenco attuale dei runtime supportati.

Trigger basati su connettore

Un trigger gestito basato su un connettore esegue la tua funzione quando si verifica un evento nel servizio connesso. Lo spazio dei nomi del connettore recapita l'evento all'app per funzioni tramite HTTPS utilizzando l'endpoint webhook dell'estensione del connettore:

POST /runtime/webhooks/connector?functionName={FunctionName}&code={connector_extension_key}

{FunctionName} corrisponde al nome nell'attributo [Function]. {connector_extension_key} è il valore di una chiave di sistema che si recupera eseguendo:

{FunctionName} corrisponde al nome nel tuo decoratore @app.function_name. {connector_extension_key} è il valore di una chiave di sistema che si recupera eseguendo:

{FunctionName} corrisponde al nome indicato nella registrazione del trigger. {connector_extension_key} è il valore di una chiave di sistema che si recupera eseguendo:

az functionapp keys list \
    --resource-group <resource-group> \
    --name <function-app> \
    --query "systemKeys.connector_extension" \
    --output tsv

La configurazione del trigger nello spazio dei nomi del connettore memorizza quell'URL di callback e include la chiave di sistema in ogni callback. L'runtime Functions valida la chiave prima di eseguire la tua funzione. Per una configurazione senza segreti condivisi, puoi mettere l'autenticazione integrata di App Service davanti all'app funzione e validare un token di identità gestita dal namespace del connettore. Vedi esempio .NET: autenticazione integrata con identità gestita per il pattern completo.

Tip

Usare il piano Flex Consumption per le funzioni attivate dal connettore durante l'anteprima. Flex Consumption offre supporto per la scalabilità per istanza e per le identità gestite, in linea con il modello di autenticazione della piattaforma dei connettori.

I payload di richiesta contengono il corpo dell'evento insieme a una serie di x-ms-* intestazioni che identificano la configurazione del trigger, la connessione, il tipo di evento e un ID di correlazione. Quando il connettore gestito ha un modello SDK, il runtime deserializza direttamente il payload in quel modello. Per i connettori gestiti senza client SDK, la tua funzione riceve il corpo JSON grezzo.

L'esempio seguente mostra una funzione che viene attivata quando arriva un nuovo messaggio di posta elettronica in una cassetta postale di Office 365 Outlook. La registrazione del trigger è per lingua; La configurazione del trigger nello spazio dei connettori è la stessa in tutti i casi.

using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Extensions.Connector;
using Azure.Connectors.Sdk.Office365.Models;
using Microsoft.Extensions.Logging;

public class OnNewEmail
{
    private readonly ILogger<OnNewEmail> _logger;

    public OnNewEmail(ILogger<OnNewEmail> logger) => _logger = logger;

    [Function("OnNewEmail")]
    public IActionResult Run(
        [ConnectorTrigger()] Office365OnNewEmailTriggerPayload payload)
    {
        var emails = payload?.Body?.Value ?? [];
        foreach (var email in emails)
        {
            _logger.LogInformation(
                "Received email from {From} with subject '{Subject}'.",
                email.From, email.Subject);
        }

        return new OkResult();
    }
}

Il modello Office365OnNewEmailTriggerPayload e altri tipi di payload dell'operazione provengono da Azure.Connectors.Sdk.Office365.Models. Per la mappatura completa tra operazioni e payload, consulta Operations to Funzioni di Azure signature mapping.

import azure.functions as func
import json
import logging

app = func.FunctionApp()

@app.function_name(name="OnNewEmail")
@app.connector_trigger(arg_name="payload")
def on_new_email(payload: str) -> None:
    data = json.loads(payload)
    emails = data.get("body", {}).get("value", [])
    for email in emails:
        logging.info(
            "Received email from %s with subject '%s'.",
            email.get("from"), email.get("subject"))

Per l'operazione Office 365 OnNewEmailV3 nello specifico, è possibile usare il decoratore tipizzato di azurefunctions-extensions-connectors:

import azure.functions as func
import azurefunctions.extensions.connectors.office365 as office365
import logging

app = func.FunctionApp()

@app.function_name(name="OnNewEmail")
@app.connector_trigger(arg_name="email")
def on_new_email(email: office365.ClientReceiveMessage) -> None:
    logging.info(
        "Received email from %s with subject '%s'.",
        email.from_, email.subject)
import { InvocationContext } from '@azure/functions';
import {
    connectors,
    EmailTriggerContext,
} from '@azure/functions-extensions-connectors';

connectors.office365.onNewEmail('OnNewEmail', {
    handler: async (
        context: EmailTriggerContext,
        invocationContext: InvocationContext,
    ) => {
        for (const email of context.emails) {
            invocationContext.log(
                `Received email from '${email.from}' with subject '${email.subject}'.`,
            );
        }
    },
});

Per qualsiasi connettore che non dispone ancora di un punto di ingresso tipizzato, usare il generico app.connectorTrigger da @azure/functions:

import { app, InvocationContext } from '@azure/functions';

app.connectorTrigger('OnNewItem', {
    handler: async (payload: unknown, context: InvocationContext) => {
        const data = typeof payload === 'string' ? JSON.parse(payload) : payload;
        const items: Record<string, unknown>[] = (data as any)?.body?.value ?? [];
        for (const item of items) {
            context.log(`Item ID: ${item.Id}`);
        }
    },
});

L'attivatore del connettore non è disponibile in questa lingua per l'anteprima pubblica.

Si crea la configurazione del trigger nel namespace del connettore tramite interfaccia della riga di comando di Azure, ARM o Bicep. Questo passaggio fa parte della piattaforma del connettore ed è documentato nel content set del connettore. Functions non include comandi di configurazione propri per la registrazione dei trigger.

Autenticare le tue funzioni in un namespace del connettore

Note

Questa sezione copre l'autenticazione tra il namespace del connettore e la tua app di funzione. Per informazioni su come il namespace del connettore si autentica ai servizi upstream (Microsoft 365, Teams, SharePoint), vedere Panoramica dei connettori di Azure.

Il modello di autenticazione predefinito utilizza una chiave di sistema condivisa (connector_extension) che il namespace del connettore presenta a ogni callback. Tuttavia, le chiavi condivise non possono essere limitate a livello di singolo trigger e richiedono una rotazione coordinata tra l'app per le funzioni e il namespace del connettore. Per i carichi di lavoro di produzione, utilizza invece l'autenticazione integrata di App Service (chiamata anche Easy Auth) con un'identità gestita.

In questo schema, il namespace del connettore utilizza la propria identità gestita assegnata dal sistema o dall'utente per richiedere un token Entra ID per ogni callback. L'app per le funzioni convalida il token, verificandone il destinatario, l'emittente e l'ID oggetto del chiamante, prima che qualsiasi richiesta raggiunga l'host di Functions. Nessuna chiave condivisa, nessun segreto client, ovunque.

Per un esempio completo e funzionante, consulta questo repository: functions-connectors-net-builtinauth.

Configurazione dell'app per le funzioni

L'autenticazione predefinita viene eseguita al limite del ruolo di lavoro del servizio app, prima che il runtime di Functions riceva la richiesta. Configurarlo tramite la authsettingsV2 proprietà ARM o il suo equivalente in Bicep.

Setting Purpose
requireAuthentication: true Rifiuta qualsiasi richiesta senza un token valido (restituisce 401).
identityProviders.azureActiveDirectory.enabled: true Convalida i token di Entra ID.
registration.clientId L'ID dell'app (client) della registrazione dell'app Entra rispetto alla quale l'autenticazione integrata convalida i token.
registration.openIdIssuer URL dell'emittente per il tenant: https://login.microsoftonline.com/{tenantId}/v2.0.
validation.allowedAudiences L'ID client e l'URI identificatore dell'app Entra. I token devono contenere uno di questi destinatari nel claim aud.
validation.defaultAuthorizationPolicy.allowedPrincipals.identities Gli ID oggetto (entità) delle identità gestite autorizzate a chiamare la funzione. Qui dovrebbe essere elencata solo l'identità gestita dello spazio dei connettori. Qualsiasi token con un'attestazione diversa oid ottiene un valore 403.

L'app per le funzioni richiede anche un'identità gestita assegnata dall'utente federata alla registrazione dell'app Entra. L'autenticazione integrata usa tale credenziale di identità federata (FIC) per generare asserzioni client per l'app Entra senza dover archiviare un segreto client. Il modello Bicep imposta clientSecretSettingName su un'impostazione dell'app che contiene l'ID client dell'identità gestita assegnata dall'utente, specificando all'autenticazione integrata di usare FIC anziché un segreto.

Poiché l'autenticazione integrata convalida già ogni richiesta, puoi disabilitare il controllo ridondante della chiave di sistema in host.json, che avrebbe questo aspetto nel seguente frammento JSON:

{
    ...
    "extensions": {
        "connector": {
            "system": {
                "webhookAuthorizationLevel": "Anonymous"
            }
        }
    }
}

Configurazione dello spazio di nomi dei connettori

Lo spazio dei nomi del connettore deve avere abilitata e associata un'identità gestita assegnata dal sistema o dall'utente. Quando crei la configurazione del trigger, specifica authentication.type = ManagedServiceIdentity e authentication.identity = <resource-id-of-managed-identity> per un'identità assegnata dall'utente o ometti identity un'identità assegnata dal sistema. Specificare anche authentication.audience = <entra-app-client-id> in modo che il runtime del connettore sappia quale destinatario richiedere nel token.

Il runtime del connettore utilizza tale identità gestita per generare un token di Entra ID a ogni callback. In questo token, iss (emittente) è il tenant, aud (destinatario) è l'ID client dell'app Entra e oid (ID oggetto) è l'ID principale dell'identità. L'autenticazione predefinita convalida tutti e tre.

Anche la risorsa namespace del connettore deve poter accedere alla connessione, ad esempio a una connessione office365. Concedere questo accesso tramite una policy di accesso che elenca l'ID principale dell'identità gestita. l file di esempio Bicep mostra la configurazione completa sia per l'identità del namespace sia per il criterio di accesso alla connessione.

Elementi applicati

L'autenticazione predefinita convalida i token in ordine:

  1. Presenza del token - Token mancante o scaduto → 401
  2. Firma: verificata rispetto al JWKS dell'emittente per il tenant
  3. iss (emittente) - Deve corrispondere a openIdIssuer
  4. aud (gruppo di destinatari): deve trovarsi in allowedAudiences
  5. oid (ID oggetto/entità): deve corrispondere a una delle identità in allowedPrincipals.identities. Qualsiasi altra identità → 403

Poiché questo controllo viene eseguito al perimetro di App Service, il codice della funzione non riceve mai una richiesta che non provenga dall'identità gestita del namespace del connettore. Non serve alcun codice applicativo per il controllo di accesso.

Flusso di autenticazione

┌─────────────────────────────────────────────────────────────────┐
│  Connector namespace  (westcentralus)                           │
│  • System-assigned or user-assigned managed identity enabled    │
│  • Trigger config: authentication.type = ManagedServiceIdentity │
│                    authentication.audience = <Entra app ID>     │
│                    callbackUrl = https://<func>/runtime/…       │
└────────────────────────┬───────────────────────────────────────┘
                         │
                         │  POST callbackUrl
                         │  Authorization: Bearer <AAD token>
                         │     iss = your tenant
                         │     aud = Entra app clientId
                         │     oid = managed identity principalId
                         ▼
┌──────────────────────────────────────────────────────────────┐
│  Function App  (any region)                                  │
│                                                              │
│   ┌──────────────────────────────────────────────────────┐   │
│   │ Built-in authentication  (App Service edge)          │   │
│   │   • Validates signature, iss, aud, exp               │   │
│   │   • Checks oid ∈ allowedPrincipals.identities        │   │
│   │   → No token  → 401                                  │   │
│   │   → Wrong oid → 403                                  │   │
│   └────────────────────┬─────────────────────────────────┘   │
│                        │ pass                                │
│                        ▼                                     │
│   ┌──────────────────────────────────────────────────────┐   │
│   │ /runtime/webhooks/connector                          │   │
│   │   (webhookAuthorizationLevel = Anonymous)            │   │
│   └────────────────────┬─────────────────────────────────┘   │
│                        ▼                                     │
│   ┌──────────────────────────────────────────────────────┐   │
│   │ Your function(payload)                               │   │
│   └──────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────┘
                         ▲
                         │ FIC (federated identity credential)
         ┌───────────────┴────────────────┐
         │  Entra app registration         │
         │  (federated to function-app MI) │
         └─────────────────────────────────┘

Uso dei connettori nel codice

L'SDK del connettore consente alla tua funzione di chiamare le operazioni del connettore come azioni in uscita. L'interfaccia client utilizza lo stesso connettore gestito sottostante nello spazio dei nomi del connettore che ne attiva l'uso, quindi un singolo connettore gestito può supportare sia i trigger in ingresso sia le chiamate in uscita per lo stesso account di servizio.

In .NET ogni connettore fornisce un client tipizzato (ad esempio, Office365Client, Office365UsersClient, TeamsClient) in Azure.Connectors.Sdk.{Service}. Il costruttore client acquisisce l'URL di runtime della connessione e una credenziale.

Lo schema seguente proviene dall'esempio di Teams end-to-end per la ricerca dell'utente tramite email:

using Azure.Core;
using Azure.Identity;
using Azure.Connectors.Sdk.Office365;
using Azure.Connectors.Sdk.Office365Users;
using Azure.Connectors.Sdk.Teams;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions
{
    ManagedIdentityClientId = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID")
});

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication()
    .ConfigureServices(services =>
    {
        services.AddSingleton<TokenCredential>(credential);

        services.AddSingleton(sp => new Office365Client(
            new Uri(Environment.GetEnvironmentVariable("OFFICE365_CONNECTION_RUNTIME_URL")!),
            sp.GetRequiredService<TokenCredential>()));

        services.AddSingleton(sp => new Office365UsersClient(
            new Uri(Environment.GetEnvironmentVariable("OFFICE365USERS_CONNECTION_RUNTIME_URL")!),
            sp.GetRequiredService<TokenCredential>()));

        services.AddSingleton(sp => new TeamsClient(
            new Uri(Environment.GetEnvironmentVariable("TEAMS_CONNECTION_RUNTIME_URL")!),
            sp.GetRequiredService<TokenCredential>()));
    })
    .Build();

host.Run();

Le impostazioni *_CONNECTION_RUNTIME_URL puntano all'endpoint di runtime relativo a ciascuna connessione nello spazio dei nomi del connettore. Inserisci i client nella tua funzione e chiama metodi tipizzati come UserProfileAsync, GetEmailsAsync o FlagAsync. È anche possibile chiamare i client SDK da trigger che non usano connettori, ad esempio un trigger HTTP che pubblica in Teams.

In Python, installa azure-connectors per i client tipizzati (ad esempio, office365, teams, office365Users). I client accettano l'URL di runtime per ogni connessione e una credenziale di accesso. La copertura delle azioni SDK si sta espandendo.

In Node.js, installare @azure/connectors per i client tipizzati (ad esempio, office365, teams, office365Users). I client accettano l'URL di runtime per ogni connessione e una credenziale di accesso. La copertura delle azioni SDK si sta espandendo.

L'SDK del connettore non è disponibile in questi linguaggi per l'anteprima pubblica.