{"meta":{"title":"управляемое удостоверение Azure с помощью BYOK","intro":"БЁК (принеси свой ключ) пакета SDK GitHub Copilot поддерживает статические ключи API, но Azure развертывания часто используют управляемое удостоверение (Microsoft Entra ID) вместо долгоживущего ключа. Пакет SDK GitHub Copilot предназначен для создания с помощью пакета SDK Azure Identity SDK для обеспечения максимальной гибкости. Предоставьте обратный вызов поставщика маркеров носителя, который может получать новые маркеры по запросу с помощью API пакета SDK для Azure идентификации.","product":"GitHub Copilot","breadcrumbs":[{"href":"/ru/copilot","title":"GitHub Copilot"},{"href":"/ru/copilot/how-tos","title":"Инструкции"},{"href":"/ru/copilot/how-tos/copilot-sdk","title":"Второй пилот SDK"},{"href":"/ru/copilot/how-tos/copilot-sdk/setup","title":"Настройте Copilot SDK"},{"href":"/ru/copilot/how-tos/copilot-sdk/setup/azure-managed-identity","title":"Управляемая идентификация Azure"}],"documentType":"article"},"body":"# управляемое удостоверение Azure с помощью BYOK\n\nБЁК (принеси свой ключ) пакета SDK GitHub Copilot поддерживает статические ключи API, но Azure развертывания часто используют управляемое удостоверение (Microsoft Entra ID) вместо долгоживущего ключа. Пакет SDK GitHub Copilot предназначен для создания с помощью пакета SDK Azure Identity SDK для обеспечения максимальной гибкости. Предоставьте обратный вызов поставщика маркеров носителя, который может получать новые маркеры по запросу с помощью API пакета SDK для Azure идентификации.\n\n<!-- markdownlint-disable GHD046 GHD005 -->\n\n<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->\n\nВ этом руководстве показано, как использовать API пакета SDK Azure identity SDK для проверки подлинности с помощью моделей Microsoft Foundry с помощью пакета SDK GitHub Copilot. Большинство языков используется`DefaultAzureCredential`; Rust используется `DeveloperToolsCredential` локально и `ManagedIdentityCredential` в Azure.\n\n## Принцип работы\n\nMicrosoft конечная точка OpenAI, совместимая с OpenAI,`https://<resource-name>.openai.azure.com/openai/v1/` принимает маркеры носителя из Microsoft Entra ID вместо статических ключей API. В этом руководстве используется обратный вызов поставщика маркеров, поэтому среда выполнения пакета SDK GitHub Copilot может запрашивать новые токены по запросу.\n\nВ качестве примера используется Python поток:\n\n1. Настройте `DefaultAzureCredential` среду.\n2. Передайте обратный вызов в `bearer_token_provider` конфигурации поставщика BYOK, которая используется `DefaultAzureCredential` для получения маркера для `https://ai.azure.com/.default` области.\n3. Пусть пакет SDK GitHub Copilot запрашивает новые маркеры по запросу через этот обратный вызов.\n\n![Диаграмма: диаграмма последовательностей, показывающая описанный процесс.](/assets/images/help/copilot/copilot-sdk/setup-azure-managed-identity-diagram-0.png)\n\n## Примеры кода\n\n### Необходимые условия\n\nУстановите пакеты SDK для удостоверений Azure и GitHub Copilot для вашего языка:\n\n<div class=\"ghd-codetabs\">\n<div class=\"ghd-codetab\" data-lang=\"dotnet\" data-label=\".NET\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">.NET</div>\n\n<!-- docs-validate: skip -->\n\n```bash\ndotnet add package GitHub.Copilot.SDK\ndotnet add package Azure.Core\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"go\" data-label=\"Go\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Go</div>\n\n<!-- docs-validate: skip -->\n\n```bash\ngo get github.com/github/copilot-sdk/go\ngo get github.com/Azure/azure-sdk-for-go/sdk/azidentity\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"java\" data-label=\"Java\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Java</div>\n\n<!-- docs-validate: skip -->\n\n```xml\n<dependency>\n    <groupId>com.github</groupId>\n    <artifactId>copilot-sdk-java</artifactId>\n    <version>${copilot.sdk.version}</version>\n</dependency>\n\n<dependency>\n    <groupId>com.azure</groupId>\n    <artifactId>azure-identity</artifactId>\n    <version>${azure.identity.version}</version>\n</dependency>\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"python\" data-label=\"Python\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Python</div>\n\n<!-- docs-validate: skip -->\n\n```bash\npip install github-copilot-sdk azure-identity\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"rust\" data-label=\"Rust\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Rust</div>\n\n<!-- docs-validate: skip -->\n\n```bash\ncargo add github-copilot-sdk azure_identity azure_core\ncargo add tokio --features macros,rt-multi-thread\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"typescript\" data-label=\"TypeScript\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">TypeScript</div>\n\n<!-- docs-validate: skip -->\n\n```bash\nnpm install @github/copilot-sdk @azure/identity\n```\n\n</div>\n\n</div>\n\n### Использование обратного вызова поставщика маркеров\n\nИспользуйте этот подход, если требуется, чтобы среда выполнения пакета SDK GitHub Copilot запрашивала новые маркеры по запросу через предоставленный обратный вызов. Пакет SDK для идентификации Azure обрабатывает кэширование маркеров и время обновления.\n\nНиже приведены реализации, относящиеся к языку:\n\n<div class=\"ghd-codetabs\">\n<div class=\"ghd-codetab\" data-lang=\"dotnet\" data-label=\".NET\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">.NET</div>\n\n<!-- docs-validate: skip -->\n\n```csharp\nusing Azure.Core;\nusing Azure.Identity;\nusing GitHub.Copilot;\n\nDefaultAzureCredential credential = new(\n    DefaultAzureCredential.DefaultEnvironmentVariableName);\nawait using CopilotClient client = new();\nstring foundryUrl = Environment.GetEnvironmentVariable(\"FOUNDRY_RESOURCE_URL\")!;\n\nawait using CopilotSession session = await client.CreateSessionAsync(new SessionConfig\n{\n    Model = \"gpt-5.5\",\n    Provider = new ProviderConfig\n    {\n        Type = \"openai\",\n        BaseUrl = $\"{foundryUrl}/openai/v1/\",\n        BearerTokenProvider = async _ =>\n        {\n            AccessToken token = await credential.GetTokenAsync(\n                new TokenRequestContext([\"https://ai.azure.com/.default\"]));\n            return token.Token;\n        },\n        WireApi = \"responses\",\n    },\n});\n\nAssistantMessageEvent? response = await session.SendAndWaitAsync(\n    new MessageOptions { Prompt = \"Hello from Managed Identity!\" });\nConsole.WriteLine(response?.Data.Content);\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"go\" data-label=\"Go\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Go</div>\n\n<!-- docs-validate: skip -->\n\n```golang\npackage main\n\nimport (\n    \"context\"\n    \"fmt\"\n    \"log\"\n    \"os\"\n    \"time\"\n\n    \"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy\"\n    \"github.com/Azure/azure-sdk-for-go/sdk/azidentity\"\n    copilot \"github.com/github/copilot-sdk/go\"\n)\nfunc main() {\n    opts := azidentity.DefaultAzureCredentialOptions{RequireAzureTokenCredentials: true}\n    credential, err := azidentity.NewDefaultAzureCredential(&opts)\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    getBearerToken := func(args copilot.ProviderTokenArgs) (string, error) {\n        token, err := credential.GetToken(context.Background(), policy.TokenRequestOptions{\n            Scopes: []string{\"https://ai.azure.com/.default\"},\n        })\n        if err != nil {\n            return \"\", err\n        }\n        return token.Token, nil\n    }\n\n    client := copilot.NewClient(nil)\n    if err := client.Start(context.Background()); err != nil {\n        log.Fatal(err)\n    }\n    defer client.Stop()\n\n    foundryURL := os.Getenv(\"FOUNDRY_RESOURCE_URL\")\n\n    session, err := client.CreateSession(context.Background(), &copilot.SessionConfig{\n        Model: \"gpt-5.5\",\n        Provider: &copilot.ProviderConfig{\n            Type:                \"openai\",\n            BaseURL:             fmt.Sprintf(\"%s/openai/v1/\", foundryURL),\n            BearerTokenProvider: getBearerToken,\n            WireAPI:             \"responses\",\n        },\n    })\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer session.Disconnect()\n\n    ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)\n    defer cancel()\n\n    response, err := session.SendAndWait(ctx, copilot.MessageOptions{\n        Prompt: \"Hello from Managed Identity!\",\n    })\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    if response != nil {\n        if data, ok := response.Data.(*copilot.AssistantMessageData); ok {\n            fmt.Println(data.Content)\n        }\n    }\n}\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"java\" data-label=\"Java\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Java</div>\n\n<!-- docs-validate: skip -->\n\n```java\nimport com.azure.core.credential.TokenRequestContext;\nimport com.azure.identity.AzureIdentityEnvVars;\nimport com.azure.identity.DefaultAzureCredentialBuilder;\nimport com.github.copilot.CopilotClient;\nimport com.github.copilot.generated.AssistantMessageEvent;\nimport com.github.copilot.rpc.BearerTokenProvider;\nimport com.github.copilot.rpc.MessageOptions;\nimport com.github.copilot.rpc.ProviderConfig;\nimport com.github.copilot.rpc.SessionConfig;\n\npublic class ManagedIdentityExample {\n    public static void main(String[] args) throws Exception {\n        var credential = new DefaultAzureCredentialBuilder()\n                .requireEnvVars(AzureIdentityEnvVars.AZURE_TOKEN_CREDENTIALS)\n                .build();\n        BearerTokenProvider tokenProvider = providerArgs ->\n            credential\n                .getToken(new TokenRequestContext().addScopes(\"https://ai.azure.com/.default\"))\n                .map(accessToken -> accessToken.getToken())\n                .toFuture();\n        String foundryUrl = System.getenv(\"FOUNDRY_RESOURCE_URL\");\n\n        try (var client = new CopilotClient()) {\n            client.start().get();\n\n            var session = client.createSession(new SessionConfig()\n                    .setModel(\"gpt-5.5\")\n                    .setProvider(new ProviderConfig()\n                            .setType(\"openai\")\n                            .setBaseUrl(foundryUrl + \"/openai/v1/\")\n                            .setBearerTokenProvider(tokenProvider)\n                            .setWireApi(\"responses\")))\n                .get();\n\n            AssistantMessageEvent response = session\n                    .sendAndWait(new MessageOptions().setPrompt(\"Hello from Managed Identity!\"))\n                    .get();\n            System.out.println(response.getData().content());\n\n            session.disconnect().get();\n        }\n    }\n}\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"python\" data-label=\"Python\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Python</div>\n\n<!-- docs-validate: skip -->\n\n```python\nimport asyncio\nimport os\n\nfrom azure.identity.aio import DefaultAzureCredential\nfrom copilot import CopilotClient\nfrom copilot.session import PermissionHandler, ProviderConfig\n\nasync def main():\n    credential = DefaultAzureCredential(require_envvar=True)\n    async def get_bearer_token(_args) -> str:\n        token = await credential.get_token(\"https://ai.azure.com/.default\")\n        return token.token\n\n    foundry_url = os.environ[\"FOUNDRY_RESOURCE_URL\"]\n\n    client = CopilotClient()\n    await client.start()\n\n    session = await client.create_session(\n        on_permission_request=PermissionHandler.approve_all,\n        model=\"gpt-5.5\",\n        provider=ProviderConfig(\n            type=\"openai\",\n            base_url=f\"{foundry_url.rstrip('/')}/openai/v1/\",\n            bearer_token_provider=get_bearer_token,\n            wire_api=\"responses\",\n        ),\n    )\n\n    response = await session.send_and_wait(\"Hello from Managed Identity!\")\n    print(response.data.content)\n\n    await client.stop()\n    await credential.close()\n\nasyncio.run(main())\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"rust\" data-label=\"Rust\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Rust</div>\n\n<!-- docs-validate: skip -->\n\n```rust\nuse std::sync::Arc;\n\nuse azure_core::credentials::TokenCredential;\nuse azure_identity::{DeveloperToolsCredential, ManagedIdentityCredential};\nuse github_copilot_sdk::{BearerTokenError, Client, ClientOptions, MessageOptions, ProviderTokenArgs};\nuse github_copilot_sdk::types::{ProviderConfig, SessionConfig};\n\nfn credential_for_environment() -> azure_core::Result<Arc<dyn TokenCredential>> {\n    match std::env::var(\"AZURE_TOKEN_CREDENTIALS\").as_deref() {\n        Ok(\"ManagedIdentityCredential\") => Ok(ManagedIdentityCredential::new(None)?),\n        _ => Ok(DeveloperToolsCredential::new(None)?),\n    }\n}\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let credential = credential_for_environment()?;\n    let foundry_url = std::env::var(\"FOUNDRY_RESOURCE_URL\")?;\n\n    let get_bearer_token = {\n        let credential = credential.clone();\n        move |_args: ProviderTokenArgs| {\n            let credential = credential.clone();\n            async move {\n                let token = credential\n                    .get_token(&[\"https://ai.azure.com/.default\"], None)\n                    .await\n                    .map_err(|err| BearerTokenError::message(err.to_string()))?;\n                Ok(token.token.secret().to_string())\n            }\n        }\n    };\n\n    let mut provider = ProviderConfig::default();\n    provider.provider_type = Some(\"openai\".to_string());\n    provider.base_url = format!(\"{}/openai/v1/\", foundry_url.trim_end_matches('/'));\n    provider.bearer_token_provider = Some(Arc::new(get_bearer_token));\n    provider.wire_api = Some(\"responses\".to_string());\n\n    let mut config = SessionConfig::default();\n    config.model = Some(\"gpt-5.5\".to_string());\n    config.provider = Some(provider);\n\n    let client = Client::start(ClientOptions::default()).await?;\n    let session = client.create_session(config).await?;\n\n    session\n        .send_and_wait(MessageOptions::new(\"Hello from Managed Identity!\"))\n        .await?;\n\n    session.disconnect().await?;\n    client.stop().await?;\n    Ok(())\n}\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"typescript\" data-label=\"TypeScript\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">TypeScript</div>\n\n<!-- docs-validate: skip -->\n\n```typescript\nimport { DefaultAzureCredential } from \"@azure/identity\";\nimport { CopilotClient } from \"@github/copilot-sdk\";\n\nconst credential = new DefaultAzureCredential({\n  requiredEnvVars: [\"AZURE_TOKEN_CREDENTIALS\"],\n});\nconst getBearerToken = async () => {\n  const tokenResponse = await credential.getToken(\"https://ai.azure.com/.default\");\n  return tokenResponse.token;\n};\n\nconst client = new CopilotClient();\n\nconst session = await client.createSession({\n  model: \"gpt-5.5\",\n  provider: {\n    type: \"openai\",\n    baseUrl: `${process.env.FOUNDRY_RESOURCE_URL}/openai/v1/`,\n    bearerTokenProvider: getBearerToken,\n    wireApi: \"responses\",\n  },\n});\n\nconst response = await session.sendAndWait({ prompt: \"Hello from Managed Identity!\" });\nconsole.log(response?.data.content);\n\nawait client.stop();\n```\n\n</div>\n\n</div>\n\n## Конфигурация среды\n\n| Переменная                                                                                                                                                                                                                                                                                 | Description                                                                                                                                                                                           | Пример                                   |\n| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- |\n| `AZURE_TOKEN_CREDENTIALS`                                                                                                                                                                                                                                                                  | При запуске в **Azure** установите на `ManagedIdentityCredential`. При **локальном** запуске установите его либо `dev` на имя учетных `AzureCliCredential`данных инструмента разработчика, например . | `ManagedIdentityCredential`              |\n| `AZURE_CLIENT_ID`                                                                                                                                                                                                                                                                          |                                                                                                                                                                                                       |                                          |\n| *Необязательное поле.* При запуске в **Azure** задайте для этого идентификатор клиента управляемого удостоверения, назначаемого пользователем при использовании`ManagedIdentityCredential`. Если этот параметр не задан, Azure использует управляемое удостоверение, назначаемое системой. | `11111111-2222-3333-4444-555555555555`                                                                                                                                                                |                                          |\n| `FOUNDRY_RESOURCE_URL`                                                                                                                                                                                                                                                                     | Ваш URL ресурса Microsoft Foundry                                                                                                                                                                     | `https://<my-resource>.openai.azure.com` |\n\nПеременная среды ключа API не требуется. Проверка подлинности обрабатывается учетными данными удостоверения Azure. В .NET, Go, Java, Python и TypeScript `DefaultAzureCredential` автоматически поддерживает следующее:\n\n* **Управляемое удостоверение** (назначаемое системой или назначаемое пользователем): для Azure размещенных приложений\n* **Azure CLI** (`az login`): для местного развития\n* **Переменные среды** (`AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, `AZURE_CLIENT_SECRET`): для принципов сервисов\n* **Идентификация рабочей** нагрузки: для Kubernetes\n\nВ .NET, Go, Java, Python и TypeScript `ManagedIdentityCredential` считывается`AZURE_CLIENT_ID`, чтобы выбрать управляемое удостоверение, назначаемое пользователем. Rust — это исключение из этого руководства.\n\nВ Rust используется `DeveloperToolsCredential` для локальной разработки и `ManagedIdentityCredential` выполнения в Azure. Сведения о других языках см. в `DefaultAzureCredential` документации по полной цепочке учетных данных:\n\n* [.NET](https://aka.ms/azsdk/net/identity/credential-chains#defaultazurecredential-overview)\n* [Go](https://aka.ms/azsdk/go/identity/credential-chains#defaultazurecredential-overview)\n* [Java](https://aka.ms/azsdk/java/identity/credential-chains#defaultazurecredential-overview)\n* [Python](https://aka.ms/azsdk/python/identity/credential-chains#defaultazurecredential-overview)\n* [TypeScript](https://aka.ms/azsdk/js/identity/credential-chains#defaultazurecredential-overview)\n\n## Когда следует использовать этот шаблон\n\n| Scenario                                                    | Recommendation                                                                  |\n| ----------------------------------------------------------- | ------------------------------------------------------------------------------- |\n| Azure-хостируемое приложение с управляемой идентичностью    |                                                                                 |\n| ✅ Используйте этот шаблон                                   |                                                                                 |\n| Приложение с существующим принципом сервиса Microsoft Entra |                                                                                 |\n| ✅ Используйте этот шаблон                                   |                                                                                 |\n| Местное развитие с `az login`                               |                                                                                 |\n| ✅ Используйте этот шаблон                                   |                                                                                 |\n| Не-Azure среда со статическим API-ключом                    | Используйте [автозаголовок](/ru/copilot/how-tos/copilot-sdk/auth/byok)          |\n| Доступна подписка GitHub Copilot                            | Используйте [автозаголовок](/ru/copilot/how-tos/copilot-sdk/setup/github-oauth) |\n\n## См. также\n\n* [БЁК (принеси свой ключ)](/ru/copilot/how-tos/copilot-sdk/auth/byok): Статическая конфигурация ключа API\n* [Настройка серверных сервисов](/ru/copilot/how-tos/copilot-sdk/setup/backend-services): Развертывание на стороне сервера"}