Выполнение автоматизированных тестов интеграции

Как разработчик вы хотите выполнять автоматические тесты интеграции в разрабатываемых приложениях. Вызов API, защищенного платформой удостоверений Майкрософт (или другими защищенными API, такими как Microsoft Graph), в автоматизированных тестах интеграции является сложной задачей. Для Azure AD часто требуется интерактивный запрос на вход пользователя, который трудно автоматизировать. В этой статье описывается, как можно использовать неинтерактивный поток предоставления учетных данных владельца ресурса (ROPC) для автоматического входа пользователей в целях тестирования.

Чтобы подготовиться к автоматизированным тестам интеграции, создайте тестовых пользователей, создайте и настройте регистрацию приложения и при необходимости внесите некоторые изменения в конфигурацию клиента. Для выполнения некоторых из этих действий требуются права администратора. Кроме того, Майкрософт не рекомендует использовать поток ROPC в рабочей среде. Создайте отдельный тестовый клиент, администратором которого вы являетесь, чтобы можно было безопасно и эффективно выполнять автоматизированные тесты интеграции.

Предупреждение

Майкрософт не рекомендует использовать поток ROPC в рабочей среде. В большинстве случаев в рабочей среде доступны и рекомендуются более безопасные альтернативы. Для потока ROPC нужен очень высокий уровень доверия в приложении, и он связан с рисками, которых нет в других потоках проверки подлинности. Используйте этот поток только в целях тестирования в отдельном тестовом клиенте и только с тестовыми пользователями.

Важно!

  • Платформа Microsoft Identity поддерживает ROPC для клиентов AAD, но не для личных учетных записей. Это означает, что придется использовать конечную точку клиента (https://login.microsoftonline.com/{TenantId_or_Name}) или конечную точку organizations.
  • Пользователи личных учетных записей, приглашенные в клиент Azure AD, не могут использовать ROPC.
  • Учетные записи без паролей не могут войти в систему с помощью учетных данных владельца ресурса. То есть, такие функции, как вход по SMS, FIDO, а также приложение Authenticator не будут работать для этого потока.
  • Если пользователи должны использовать для входа в приложение многофакторную проверку подлинности (MFA), они будут заблокированы.
  • ROPC не поддерживается в сценариях гибридной федерации удостоверений (например, Azure AD и службы федерации Active Directory (AD FS), используемые для проверки подлинности локальных учетных записей). Если пользователи полностью перенаправляются на страницу локальных поставщиков удостоверений, Azure AD не сможет проверить имя пользователя и пароль для этого поставщика удостоверений. Однако с ROPC поддерживается сквозная проверка подлинности.
  • Существует следующее исключение из сценария гибридной федерации удостоверений: политика обнаружения домашней области со свойством AllowCloudPasswordValidation, для которого задано значение TRUE, позволит использовать поток учетных данных владельца ресурса для федеративных пользователей, если локальный пароль синхронизируется с облаком. Дополнительные сведения см. в разделе Включение прямой проверки подлинности ROPC для федеративных пользователей в устаревших приложениях.

Создайте отдельный тестовый клиент

Использовать поток проверки подлинности ROPC в рабочей среде рискованно, поэтому создайте отдельный клиент для тестирования приложений. Можно использовать существующий тестовый клиент, но необходимо быть администратором в клиенте, так как для выполнения некоторых действий требуются права администратора.

создавать и настраивать хранилище ключей;

Рекомендуем безопасно хранить имена и пароли тестовых пользователей в качестве секретов в Azure Key Vault. Когда вы будете выполнять тесты, они будут запускаться в контексте субъекта безопасности. Участник безопасности — это пользователь Azure AD, если вы запускаете тесты локально (например, в Visual Studio или Visual Studio Code), или субъект-служба или управляемое удостоверение, если вы выполняете тесты в Azure Pipelines или другом ресурсе Azure. У субъекта-службы должны быть разрешения на чтение и вывод списка секретов, чтобы средство выполнения теста могло получать имена и пароли тестовых пользователей из хранилища ключей. Дополнительные сведения см. в статье Проверка подлинности в Azure Key Vault.

  1. Создайте новое хранилище ключей, если у вас его нет.
  2. Запишите значение свойства URI хранилища (в формате https://<your-unique-keyvault-name>.vault.azure.net/), так как оно будет использоваться в примере теста позже в этой статье.
  3. Назначьте политику доступа для субъекта безопасности, выполняющего тесты. Предоставьте пользователю, субъекту-службе или управляемому удостоверению разрешение на получение и вывод списка секретов в хранилище ключей.

Создание тестовых пользователей

Создайте тестовых пользователей в клиенте для тестирования. Так как тестовые пользователи не являются реальными людьми, рекомендуется назначать сложные пароли и безопасно хранить их в качестве секретов в Azure Key Vault.

  1. На портале Azureвыберите Azure Active Directory.
  2. Перейдите в раздел Пользователи.
  3. Нажмите Создать пользователя и создайте одну или несколько учетных записей тестовых пользователей в каталоге.
  4. В примере теста далее в этой статье используется один тестовый пользователь. Добавьте имя и пароль тестового пользователя в качестве секретов в созданном ранее хранилище ключей. Добавьте имя пользователя в качестве секрета с именем TestUserName и паролем в качестве секрета с именем TestPassword.

Создание и настройка регистрации приложения

Зарегистрируйте приложение, которое выступает в качестве клиентского приложения при вызове API во время тестирования. Это не должно быть приложение, выполняемое в рабочей среде. У вас должно быть отдельное приложение для использования только в целях тестирования.

Регистрация приложения

Создать регистрацию приложения. Вы можете выполнить действия, описанные в кратком руководстве по регистрации приложений. Вам не нужно добавлять URI перенаправления или учетные данные, поэтому вы можете пропустить эти разделы.

Запишите значение свойства Идентификатор приложения (клиента), так как оно будет использоваться в примере теста позже в этой статье.

Включение в приложении общедоступных потоков клиентов

ROPC — это общедоступный поток клиента, поэтому необходимо включить приложение для общедоступных потоков клиентов. Из регистрации приложения на портале Azure перейдите в раздел Проверка подлинности>Расширенные параметры>Разрешить общедоступные потоки клиентов. Переведите переключатель в положение Да.

Так как ROPC не является интерактивным потоком, вы не увидите экран запроса согласия во время выполнения. Заранее дайте согласие на разрешения, чтобы избежать ошибок при получении маркеров.

Добавьте разрешения в приложение. Не добавляйте в приложение конфиденциальные разрешения или права доступа с высоким уровнем привилегий. В целях тестирования мы рекомендуем ограничиться основными сценариями интеграции, связанными с интеграцией с Azure AD.

Из регистрации приложения на портале Azure перейдите в раздел Разрешения API>Добавить разрешение. Добавьте разрешения, необходимые для вызова интерфейсов API, которые вы будете использовать. В тестовом примере в этой статье используются разрешения https://graph.microsoft.com/User.Read и https://graph.microsoft.com/User.ReadBasic.All.

После добавления разрешений необходимо согласиться с ними. Способ предоставления согласия на разрешения зависит от того, находится ли тестовое приложение в том же клиенте, что и регистрация приложения, и являетесь ли вы администратором в клиенте.

Регистрация приложения и само приложение находятся в одном клиенте, и вы являетесь его администратором

Если вы планируете тестировать приложение в том же клиенте, в котором вы его зарегистрировали и где вы являетесь администратором, вы можете дать согласие на разрешения на портале Azure. В регистрации приложений на портале Azure перейдите к разделу Разрешения API и нажмите кнопку Предоставить согласие администратора для <your_tenant_name> рядом с кнопкой Добавить разрешение, а затем нажмите Да для подтверждения.

Регистрация приложения и само приложение находятся в разных клиентах или вы не являетесь администратором

Если вы не планируете тестировать приложение в том же клиенте, в котором зарегистрировали его, или вы не являетесь администратором в клиенте, вы не сможете предоставить согласие на разрешения на портале Azure. Однако вы по-прежнему можете дать согласие на некоторые разрешения, запустив запрос на вход в веб-браузере.

В регистрации приложения на портале Azure перейдите в раздел Проверка подлинности>Конфигурации платформы>Добавить платформу>Веб. Добавьте URI перенаправления "https://localhost" и нажмите Настроить.

Не существует способа дать предварительное согласие на портале Azure, если вы не являетесь администратором, поэтому отправьте следующий запрос в браузере. При появлении запроса на экране входа выполните вход с помощью тестовой учетной записи, созданной на предыдущем шаге. Дайте согласие на запрошенные разрешения. Этот шаг нужно повторить для каждого API, который вы будете вызывать, и для каждого тестового пользователя.

// Line breaks for legibility only

https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id={your_client_ID}
&response_type=code
&redirect_uri=https://localhost
&response_mode=query
&scope={resource_you_want_to_call}/.default
&state=12345

Замените {tenant} идентификатором вашего клиента, {your_client_ID} — идентификатором клиента приложения, а {resource_you_want_to_call} — URI идентификатора (например, "https://graph.microsoft.com") или идентификатором приложения API, доступ к которому вы хотите получить.

Исключение тестовых приложений и пользователей из политики MFA

Вероятно, у вашего клиента есть политика условного доступа, требующая многофакторную проверку подлинности (MFA) для всех пользователей, в соответствии с рекомендациями Майкрософт. MFA не будет работать с ROPC, поэтому необходимо исключить тестовые приложения и тестовых пользователей из этой политики.

Чтобы исключить учетные записи пользователей, выполните следующие действия:

  1. На портале Azure войдите в свой клиент. Выберите Azure Active Directory. Нажмите Безопасность на левой панели навигации и выберите Условный доступ.
  2. В разделе Политики выберите политику условного доступа, которая требует MFA.
  3. Выберите Идентификаторы пользователей или рабочих нагрузок.
  4. Откройте вкладку Исключить и поставьте флажок для пункта Пользователи и группы.
  5. Выберите учетные записи пользователей, которые следует исключить, в разделе Выбор исключенных пользователей.
  6. Нажмите Выбрать, а затем Сохранить.

Чтобы исключить тестовое приложение, выполните следующие действия:

  1. В разделе Политики выберите политику условного доступа, которая требует MFA.
  2. Выберите Облачные приложения или действия.
  3. Откройте вкладку Исключить и выберите Выбор исключенных облачных приложений.
  4. Выберите приложения, которые необходимо исключить, в списке Выбор исключенных облачных приложений.
  5. Нажмите Выбрать, а затем Сохранить.

Написание тестов для приложения

После настройки можно приступить к написанию автоматических тестов. В следующем примере кода .NET используется библиотека проверки подлинности Майкрософт (MSAL) и xUnit, распространенная платформа тестирования.

Настройка файла appsettings.json

Добавьте идентификатор клиента для созданного ранее тестового приложения, необходимые области и универсальный код ресурса (URI) хранилища ключей в файл appsettings.json тестового проекта.

{
  "Authentication": {
    "AzureCloudInstance": "AzurePublic", //Will be different for different Azure clouds, like US Gov
    "AadAuthorityAudience": "AzureAdMultipleOrgs",
    "ClientId": <your_client_ID>
  },

  "WebAPI": {
    "Scopes": [
      //For this Microsoft Graph example.  Your value(s) will be different depending on the API you're calling
      "https://graph.microsoft.com/User.Read",
      //For this Microsoft Graph example.  Your value(s) will be different depending on the API you're calling
      "https://graph.microsoft.com/User.ReadBasic.All"
    ]
  },

  "KeyVault": {
    "KeyVaultUri": "https://<your-unique-keyvault-name>.vault.azure.net//"
  }
}

Настройка клиента для использования во всех тестовых классах

Используйте SecretClient(), чтобы получить имя и пароль тестового пользователя в виде секретов из Azure Key Vault. В этом коде реализована экспоненциальная задержка для повторных попыток на случай регулирования запросов к Key Vault.

DefaultAzureCredential() выполняет проверку подлинности с помощью Azure Key Vault, получая маркер доступа из субъекта-службы, настроенного с помощью переменных среды, или управляемое удостоверение (если код выполняется в ресурсе Azure с управляемым удостоверением). Если код выполняется локально, DefaultAzureCredential использует учетные данные локального пользователя. Дополнительные сведения см. в разделе о клиентской библиотеке удостоверений Azure.

Используйте библиотеку проверки подлинности Майкрософт (MSAL) для проверки подлинности с помощью потока ROPC и получения маркера доступа. Маркер доступа передается в качестве токена носителя в HTTP-запросе.

using Xunit;
using System.Threading.Tasks;
using Microsoft.Identity.Client;
using System.Security;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using Microsoft.Extensions.Configuration;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using Azure.Core;
using System;

public class ClientFixture : IAsyncLifetime
{
    public HttpClient httpClient;

    public async Task InitializeAsync()
    {
        var builder = new ConfigurationBuilder().AddJsonFile("<path-to-json-file>");

        IConfigurationRoot Configuration = builder.Build();

        var PublicClientApplicationOptions = new PublicClientApplicationOptions();
        Configuration.Bind("Authentication", PublicClientApplicationOptions);
        var app = PublicClientApplicationBuilder.CreateWithApplicationOptions(PublicClientApplicationOptions)
            .Build();

        SecretClientOptions options = new SecretClientOptions()
        {
            Retry =
                {
                    Delay= TimeSpan.FromSeconds(2),
                    MaxDelay = TimeSpan.FromSeconds(16),
                    MaxRetries = 5,
                    Mode = RetryMode.Exponential
                 }
        };

        string keyVaultUri = Configuration.GetValue<string>("KeyVault:KeyVaultUri");
        var client = new SecretClient(new Uri(keyVaultUri), new DefaultAzureCredential(), options);

        KeyVaultSecret userNameSecret = client.GetSecret("TestUserName");
        KeyVaultSecret passwordSecret = client.GetSecret("TestPassword");

        string password = passwordSecret.Value;
        string username = userNameSecret.Value;
        string[] scopes = Configuration.GetSection("WebAPI:Scopes").Get<string[]>();
        SecureString securePassword = new NetworkCredential("", password).SecurePassword;

        AuthenticationResult result = null;
        httpClient = new HttpClient();

        try
        {
            result = await app.AcquireTokenByUsernamePassword(scopes, username, securePassword)
                .ExecuteAsync();
        }
        catch (MsalException) { }

        string accessToken = result.AccessToken;
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
    }

    public Task DisposeAsync() => Task.CompletedTask;
}

Использование в тестовых классах

В следующем примере показан тест, который вызывает Microsoft Graph. Замените этот тест на другой, который вы хотите выполнить для своего приложения или API.

public class ApiTests : IClassFixture<ClientFixture>
{
    ClientFixture clientFixture;

    public ApiTests(ClientFixture clientFixture)
    {
        this.clientFixture = clientFixture;
    }

    [Fact]
    public async Task GetRequestTest()
    {
        var testClient = clientFixture.httpClient;
        HttpResponseMessage response = await testClient.GetAsync("https://graph.microsoft.com/v1.0/me");
        var responseCode = response.StatusCode.ToString();
        Assert.Equal("OK", responseCode);
    }
}