Перенос приложения на использование бессерверных подключений с Центры событий Azure для Kafka
В этой статье объясняется, как перенести традиционные методы проверки подлинности на более безопасные, без пароля подключения с Центры событий Azure для Kafka.
Запросы приложений к Центры событий Azure для Kafka должны проходить проверку подлинности. Центры событий Azure для Kafka предоставляет различные способы безопасного подключения приложений. Одним из способов является использование строка подключения. Тем не менее, по возможности следует приоритизировать подключения без пароля в приложениях.
Подключения без пароля поддерживаются с момента Spring Cloud Azure 4.3.0. В этой статье приведено руководство по миграции для удаления учетных данных из приложений Spring Cloud Stream Kafka.
Сравнение параметров проверки подлинности
Когда приложение проходит проверку подлинности с помощью Центры событий Azure для Kafka, оно предоставляет авторизованную сущность для подключения пространства имен Центров событий. Протоколы Apache Kafka предоставляют несколько механизмов простой проверки подлинности и уровня безопасности (SASL) для проверки подлинности. В соответствии с механизмами SASL существует два варианта проверки подлинности, которые можно использовать для авторизации доступа к защищенным ресурсам: проверка подлинности Microsoft Entra и проверка подлинности подписанного URL-адреса (SAS).
Проверка подлинности Microsoft Entra
Проверка подлинности Microsoft Entra — это механизм подключения к Центры событий Azure для Kafka с помощью удостоверений, определенных в идентификаторе Microsoft Entra. С помощью проверки подлинности Microsoft Entra можно управлять удостоверениями субъектов-служб и другими службы Майкрософт в центральном расположении, что упрощает управление разрешениями.
Использование идентификатора Microsoft Entra для проверки подлинности обеспечивает следующие преимущества:
- Проверка подлинности пользователей в службах Azure в единообразном режиме.
- Управление политиками паролей и сменой паролей в одном месте.
- Несколько форм проверки подлинности, поддерживаемых идентификатором Microsoft Entra, что может устранить необходимость хранения паролей.
- Клиенты могут управлять разрешениями Центров событий с помощью внешних групп (Идентификатор Microsoft Entra).
- Поддержка проверки подлинности на основе маркеров для приложений, подключающихся к Центры событий Azure для Kafka.
Проверка подлинности на основе SAS
Центры событий также предоставляют подписанные URL-адреса (SAS) для делегированного доступа к центрам событий для ресурсов Kafka.
Хотя можно подключиться к Центры событий Azure для Kafka с SAS, его следует использовать с осторожностью. Вы должны быть старательными, чтобы никогда не подвергать строка подключения в небезопасном расположении. Любой, кто получает доступ к строка подключения, может пройти проверку подлинности. Например, существует риск того, что злоумышленник может получить доступ к приложению, если строка подключения случайно проверяется в систему управления версиями, отправляется через незащищенное сообщение электронной почты, вставленное в неправильный чат или просматриваемый кем-то, кто не должен иметь разрешения. Вместо этого авторизация доступа с помощью механизма на основе маркеров OAuth 2.0 обеспечивает более высокую безопасность и удобство использования по протоколу SAS. Рассмотрите возможность обновления приложения для использования бессерверных подключений.
Знакомство с бессерверными подключениями
С помощью бессерверного подключения можно подключиться к службам Azure, не сохраняя учетные данные в коде приложения, его файлах конфигурации или переменных среды.
Многие службы Azure поддерживают бессерверные подключения, например с помощью управляемого удостоверения Azure. Эти методы предоставляют надежные функции безопасности, которые можно реализовать с помощью DefaultAzureCredential из клиентских библиотек удостоверений Azure. В этом руководстве вы узнаете, как обновить существующее приложение для использования DefaultAzureCredential
вместо альтернативных вариантов, таких как строка подключения.
DefaultAzureCredential
поддерживает несколько способов проверки подлинности и автоматически определяет, какой из них следует использовать в среде выполнения. Такой подход позволяет приложению использовать различные способы аутентификации в разных средах (локальная среда разработки и рабочая среда) без реализации кода для конкретной среды.
Порядок и расположения, в которых DefaultAzureCredential
можно найти учетные данные, можно найти в обзоре библиотеки удостоверений Azure. Например, при локальной работе обычно будет проходить проверку подлинности с помощью учетной записи разработчика, DefaultAzureCredential
используемой для входа в Visual Studio. При развертывании приложения в Azure DefaultAzureCredential
автоматически переключается на использование управляемого удостоверения. Для такого перехода не требуется изменять код.
Чтобы обеспечить без пароля подключения, необходимо учитывать как локальную разработку, так и рабочую среду. Если строка подключения требуется в любом месте, приложение не является паролем.
В локальной среде разработки можно пройти проверку подлинности с помощью Azure CLI, Azure PowerShell, Visual Studio или подключаемых модулей Azure для Visual Studio Code или IntelliJ. В этом случае вы можете использовать эти учетные данные в приложении вместо настройки свойств.
При развертывании приложений в среде размещения Azure, такой как виртуальная машина, можно назначить управляемое удостоверение в этой среде. Затем вам не потребуется предоставить учетные данные для подключения к службам Azure.
Примечание.
Управляемое удостоверение предоставляет удостоверение безопасности для представления приложения или службы. Удостоверения управляются платформой Azure, и для них не нужно подготавливать или изменять секреты. Дополнительные сведения об управляемых удостоверениях см. в обзорной документации.
Перенос существующего приложения на использование бессерверных подключений
Ниже описано, как перенести существующее приложение для использования бессерверных подключений вместо решения SAS.
0) Подготовка рабочей среды для локальной проверки подлинности разработки
Сначала используйте следующую команду, чтобы настроить некоторые переменные среды.
export AZ_RESOURCE_GROUP=<YOUR_RESOURCE_GROUP>
export AZ_EVENTHUBS_NAMESPACE_NAME=<YOUR_EVENTHUBS_NAMESPACE_NAME>
export AZ_EVENTHUB_NAME=<YOUR_EVENTHUB_NAME>
Замените заполнители следующими значениями, которые используются в этой статье:
<YOUR_RESOURCE_GROUP>
: имя группы ресурсов, которую вы будете использовать.<YOUR_EVENTHUBS_NAMESPACE_NAME>
: имя используемого пространства имен Центры событий Azure.<YOUR_EVENTHUB_NAME>
: имя концентратора событий, который вы будете использовать.
1) Предоставление разрешения на Центры событий Azure
Если вы хотите выполнить этот пример локально с проверкой подлинности Microsoft Entra, убедитесь, что учетная запись пользователя прошел проверку подлинности с помощью набора средств Azure для IntelliJ, подключаемого модуля учетной записи Azure Visual Studio Code или Azure CLI. Кроме того, убедитесь, что учетная запись предоставлена достаточно разрешений.
В портал Azure найдите пространство имен Центров событий с помощью главной панели поиска или навигации слева.
На странице обзора Центров событий выберите элемент управления доступом (IAM) в меню слева.
На странице Контроль доступа (IAM) откройте вкладку Назначения ролей.
Выберите " Добавить " в верхнем меню и добавьте назначение ролей из результирующего раскрывающегося меню.
Используйте поле поиска, чтобы отфильтровать результаты для отображения нужной роли. В этом примере выполните поиск Центры событий Azure отправителя данных и Центры событий Azure приемника данных и выберите соответствующий результат, а затем нажмите кнопку "Далее".
В разделе "Назначение доступа" выберите "Пользователь", "Группа" или "Субъект-служба", а затем выберите "Выбрать участников".
В диалоговом окне найдите имя пользователя Microsoft Entra (обычно ваш user@domain адрес электронной почты), а затем выберите в нижней части диалогового окна.
Нажмите кнопку Проверить и назначить, чтобы перейти на последнюю страницу, а затем еще раз Проверить и назначить, чтобы завершить процесс.
Дополнительные сведения о предоставлении ролей доступа см. в статье "Авторизация доступа к ресурсам Центров событий" с помощью идентификатора Microsoft Entra.
2) Вход и перенос кода приложения для использования бессерверных подключений
Для локальной разработки убедитесь, что вы прошли проверку подлинности с той же учетной записью Microsoft Entra, которую вы назначили роль в центрах событий. Аутентификацию можно выполнить с помощью Azure CLI, Visual Studio, Azure PowerShell или других средств, таких как IntelliJ.
Войдите в Azure с помощью Azure CLI, выполнив следующую команду:
az login
Затем выполните следующие действия, чтобы обновить приложение Spring Kafka для использования подключений без пароля. Хотя и концептуально аналогично, каждая платформа использует различные сведения о реализации.
В проекте откройте файл pom.xml и добавьте следующую ссылку:
<dependency> <groupId>com.azure</groupId> <artifactId>azure-identity</artifactId> <version>1.6.0</version> </dependency>
После миграции реализуйте AuthenticationCallbackHandler и OAuthBearerToken в проекте для проверки подлинности OAuth2, как показано в следующем примере.
public class KafkaOAuth2AuthenticateCallbackHandler implements AuthenticateCallbackHandler { private static final Duration ACCESS_TOKEN_REQUEST_BLOCK_TIME = Duration.ofSeconds(30); private static final String TOKEN_AUDIENCE_FORMAT = "%s://%s/.default"; private Function<TokenCredential, Mono<OAuthBearerTokenImp>> resolveToken; private final TokenCredential credential = new DefaultAzureCredentialBuilder().build(); @Override public void configure(Map<String, ?> configs, String mechanism, List<AppConfigurationEntry> jaasConfigEntries) { TokenRequestContext request = buildTokenRequestContext(configs); this.resolveToken = tokenCredential -> tokenCredential.getToken(request).map(OAuthBearerTokenImp::new); } private TokenRequestContext buildTokenRequestContext(Map<String, ?> configs) { URI uri = buildEventHubsServerUri(configs); String tokenAudience = buildTokenAudience(uri); TokenRequestContext request = new TokenRequestContext(); request.addScopes(tokenAudience); return request; } @SuppressWarnings("unchecked") private URI buildEventHubsServerUri(Map<String, ?> configs) { String bootstrapServer = Arrays.asList(configs.get(BOOTSTRAP_SERVERS_CONFIG)).get(0).toString(); bootstrapServer = bootstrapServer.replaceAll("\\[|\\]", ""); URI uri = URI.create("https://" + bootstrapServer); return uri; } private String buildTokenAudience(URI uri) { return String.format(TOKEN_AUDIENCE_FORMAT, uri.getScheme(), uri.getHost()); } @Override public void handle(Callback[] callbacks) throws UnsupportedCallbackException { for (Callback callback : callbacks) { if (callback instanceof OAuthBearerTokenCallback) { OAuthBearerTokenCallback oauthCallback = (OAuthBearerTokenCallback) callback; this.resolveToken .apply(credential) .doOnNext(oauthCallback::token) .doOnError(throwable -> oauthCallback.error("invalid_grant", throwable.getMessage(), null)) .block(ACCESS_TOKEN_REQUEST_BLOCK_TIME); } else { throw new UnsupportedCallbackException(callback); } } } @Override public void close() { // NOOP } }
public class OAuthBearerTokenImp implements OAuthBearerToken { private final AccessToken accessToken; private final JWTClaimsSet claims; public OAuthBearerTokenImp(AccessToken accessToken) { this.accessToken = accessToken; try { claims = JWTParser.parse(accessToken.getToken()).getJWTClaimsSet(); } catch (ParseException exception) { throw new SaslAuthenticationException("Unable to parse the access token", exception); } } @Override public String value() { return accessToken.getToken(); } @Override public Long startTimeMs() { return claims.getIssueTime().getTime(); } @Override public long lifetimeMs() { return claims.getExpirationTime().getTime(); } @Override public Set<String> scope() { // Referring to https://docs.microsoft.com/azure/active-directory/develop/access-tokens#payload-claims, the scp // claim is a String, which is presented as a space separated list. return Optional.ofNullable(claims.getClaim("scp")) .map(s -> Arrays.stream(((String) s) .split(" ")) .collect(Collectors.toSet())) .orElse(null); } @Override public String principalName() { return (String) claims.getClaim("upn"); } public boolean isExpired() { return accessToken.isExpired(); } }
При создании производителя или потребителя Kafka добавьте конфигурацию, необходимую для поддержки механизма SASL/OAUTHBEARER . В следующих примерах показано, как должен выглядеть код до и после миграции. В обоих примерах замените
<eventhubs-namespace>
заполнитель именем пространства имен Центров событий.Перед миграцией код должен выглядеть следующим образом:
Properties properties = new Properties(); properties.put(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG, "<eventhubs-namespace>.servicebus.windows.net:9093"); properties.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, "SASL_SSL"); properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); properties.put(SaslConfigs.SASL_MECHANISM, "PLAIN"); properties.put(SaslConfigs.SASL_JAAS_CONFIG, String.format("org.apache.kafka.common.security.plain.PlainLoginModule required username=\"$ConnectionString\" password=\"%s\";", connectionString)); return new KafkaProducer<>(properties);
После миграции код должен выглядеть следующим образом. В этом примере замените
<path-to-your-KafkaOAuth2AuthenticateCallbackHandler>
заполнитель полным именем класса для реализованногоKafkaOAuth2AuthenticateCallbackHandler
объекта.Properties properties = new Properties(); properties.put(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG, "<eventhubs-namespace>.servicebus.windows.net:9093"); properties.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, "SASL_SSL"); properties.put(SaslConfigs.SASL_MECHANISM, "OAUTHBEARER"); properties.put(SaslConfigs.SASL_JAAS_CONFIG, "org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required"); properties.put(SaslConfigs.SASL_LOGIN_CALLBACK_HANDLER_CLASS, "<path-to-your-KafkaOAuth2AuthenticateCallbackHandler>"); return new KafkaProducer<>(properties);
Локальный запуск приложения
После внесения этих изменений кода запустите приложение локально. Новая конфигурация должна получить локальные учетные данные, если вы вошли в совместимую интегрированную среду разработки или программу командной строки, например Azure CLI, Visual Studio или IntelliJ. Роли, назначенные локальному пользователю разработки в Azure, позволят приложению подключаться к службе Azure локально.
3) Настройка среды размещения Azure
После настройки приложения использовать бессерверные подключения, и он выполняется локально, тот же код может пройти проверку подлинности в службах Azure после его развертывания в Azure. Например, приложение, развернутое в экземпляре Azure Spring Apps с назначенным управляемым удостоверением, может подключаться к Центры событий Azure для Kafka.
В этом разделе описано, как разрешить приложению выполняться в среде размещения Azure без пароля:
- Назначьте управляемое удостоверение для среды размещения Azure.
- Назначьте роли управляемому удостоверению.
Примечание.
Azure также предоставляет соединитель служб, который поможет вам подключить службу размещения к центрам событий. С помощью соединителя служб для настройки среды размещения можно опустить шаг назначения ролей управляемому удостоверению, так как соединитель службы сделает это для вас. В следующем разделе описывается, как настроить среду размещения Azure двумя способами: один через соединитель службы и другой путем настройки каждой среды размещения напрямую.
Внимание
Для команд соединителя служб требуется Azure CLI 2.41.0 или более поздней версии.
Назначение управляемого удостоверения для среды размещения Azure
Ниже показано, как назначить управляемое удостоверение, назначаемое системой, для различных веб-служб размещения. Управляемое удостоверение может безопасно подключаться к другим службам Azure с помощью конфигураций приложений, настроенных ранее.
На главной странице обзора экземпляра службы приложение Azure выберите Удостоверение в области навигации.
На вкладке "Назначаемая системой" убедитесь, что поле "Состояние" включено. Назначаемое системой удостоверение управляется Azure внутренним образом и обслуживает административные задачи. Сведения об удостоверении и его идентификаторы ни в коем случае не раскрываются в коде.
Вы также можете назначить управляемое удостоверение в среде размещения Azure с помощью Azure CLI.
Управляемое удостоверение можно назначить экземпляру службы приложение Azure с помощью команды az webapp identity assign, как показано в следующем примере.
export AZURE_MANAGED_IDENTITY_ID=$(az webapp identity assign \
--resource-group $AZ_RESOURCE_GROUP \
--name <app-service-name> \
--query principalId \
--output tsv)
Назначение роли управляемому удостоверению
Затем предоставьте разрешения управляемому удостоверению, созданному для доступа к пространству имен Центров событий. Вы можете предоставить разрешения, назначив роль управляемому удостоверению, как и у локального пользователя разработки.
Если вы подключили службы с помощью соединителя службы, вам не нужно выполнить этот шаг. Для вас были обработаны следующие необходимые конфигурации:
Если вы выбрали управляемое удостоверение при создании подключения, для приложения было создано управляемое удостоверение, назначаемое системой, и назначалось роль отправителя данных Центры событий Azure и Центры событий Azure роли приемника данных в Центрах событий.
Если вы решили использовать строка подключения, строка подключения был добавлен в качестве переменной среды приложения.
Тестирование приложения
После внесения этих изменений в код перейдите в размещенное приложение в браузере. Приложение должно успешно подключиться к Центры событий Azure для Kafka. Помните, что на распространение назначений ролей в среде Azure может потребоваться несколько минут. Теперь приложение настроено для запуска в локальной и в рабочей средах без необходимости управлять секретами в самом приложении.
Следующие шаги
Из этого учебника вы узнали, как выполнить переход приложения на подключение без пароля.
Дополнительные сведения о понятиях, описанных в этой статье, см. в следующих ресурсах: