Migrace aplikace pro použití bez hesel ve službě Azure Event Hubs pro Kafka

Tento článek vysvětluje, jak migrovat z tradičních metod ověřování na bezpečnější připojení bez hesla se službou Azure Event Hubs pro Kafka.

Žádosti aplikací do služby Azure Event Hubs pro Kafka se musí ověřit. Azure Event Hubs pro Kafka nabízí různé způsoby zabezpečeného připojení aplikací. Jedním ze způsobů je použití připojovací řetězec. Pokud je to však možné, měli byste upřednostnit připojení bez hesla ve vašich aplikacích.

Připojení bez hesla se podporují od verze Spring Cloud Azure 4.3.0. Tento článek je průvodce migrací pro odebrání přihlašovacích údajů z aplikací Spring Cloud Stream Kafka.

Porovnání možností ověřování

Když se aplikace ověří ve službě Azure Event Hubs pro Kafka, poskytne autorizovanou entitu pro připojení oboru názvů služby Event Hubs. Protokoly Apache Kafka poskytují více mechanismů SASL (Simple Authentication and Security Layer) pro ověřování. Podle mechanismů SASL existují dvě možnosti ověřování, které můžete použít k autorizaci přístupu k zabezpečeným prostředkům: ověřování Microsoft Entra a ověřování sdíleného přístupového podpisu (SAS).

Ověřování Microsoft Entra

Ověřování Microsoft Entra je mechanismus pro připojení ke službě Azure Event Hubs pro Kafka pomocí identit definovaných v Microsoft Entra ID. S ověřováním Microsoft Entra můžete spravovat identity instančního objektu a další služby Microsoft v centrálním umístění, což zjednodušuje správu oprávnění.

Použití ID Microsoft Entra pro ověřování poskytuje následující výhody:

  • Jednotné ověřování uživatelů napříč službami Azure
  • Správa zásad hesel a obměně hesel na jednom místě
  • Více forem ověřování, které podporuje ID Microsoft Entra, což může eliminovat potřebu ukládat hesla.
  • Zákazníci můžou spravovat oprávnění služby Event Hubs pomocí externích skupin (MICROSOFT Entra ID).
  • Podpora ověřování na základě tokenů pro aplikace připojující se ke službě Azure Event Hubs pro Kafka

Ověřování SAS

Služba Event Hubs také poskytuje sdílené přístupové podpisy (SAS) pro delegovaný přístup ke službě Event Hubs pro prostředky Kafka.

I když se dá připojit ke službě Azure Event Hubs pro Kafka pomocí SAS, měli byste ho používat s opatrností. Musíte být usilovní, abyste nikdy nezpřístupnili připojovací řetězec v nezabezpečeném místě. Každý, kdo získá přístup k připojovací řetězec, se může ověřit. Existuje například riziko, že uživatel se zlými úmysly může získat přístup k aplikaci, pokud se připojovací řetězec omylem přihlásí ke správě zdrojového kódu, odešle se prostřednictvím nezabezpečeného e-mailu, vloží do nesprávného chatu nebo ho někdo, kdo by neměl mít oprávnění. Místo toho autorizace přístupu pomocí mechanismu založeného na tokenech OAuth 2.0 poskytuje vynikající zabezpečení a snadné použití přes SAS. Zvažte aktualizaci aplikace tak, aby používala připojení bez hesla.

Představujeme připojení bez hesla

S připojením bez hesla se můžete připojit ke službám Azure, aniž byste museli ukládat přihlašovací údaje v kódu aplikace, jeho konfiguračních souborech nebo v proměnných prostředí.

Mnoho služeb Azure podporuje připojení bez hesla, například prostřednictvím spravované identity Azure. Tyto techniky poskytují robustní funkce zabezpečení, které můžete implementovat pomocí DefaultAzureCredential z klientských knihoven identit Azure. V tomto kurzu se dozvíte, jak aktualizovat existující aplikaci tak, aby používala DefaultAzureCredential místo alternativ, jako jsou připojovací řetězec.

DefaultAzureCredential podporuje více metod ověřování a automaticky určuje, které metody by se měly používat za běhu. Tento přístup umožňuje vaší aplikaci používat různé metody ověřování v různých prostředích (místní vývoj a produkční prostředí) bez implementace kódu specifického pro prostředí.

Pořadí a umístění, ve kterých DefaultAzureCredential se hledají přihlašovací údaje, najdete v přehledu knihovny identit Azure. Pokud například pracujete místně, bude se obecně ověřovat pomocí účtu, DefaultAzureCredential který vývojář použil k přihlášení k sadě Visual Studio. Po nasazení aplikace do Azure DefaultAzureCredential se automaticky přepne na použití spravované identity. Pro tento přechod nejsou vyžadovány žádné změny kódu.

Pokud chcete zajistit, aby připojení byla bez hesla, musíte vzít v úvahu místní vývoj i produkční prostředí. Pokud se připojovací řetězec vyžaduje na jiném místě, aplikace není bez hesla.

V místním vývojovém prostředí se můžete ověřit pomocí Azure CLI, Azure PowerShellu, sady Visual Studio nebo modulů plug-in Azure pro Visual Studio Code nebo IntelliJ. V takovém případě můžete místo konfigurace vlastností použít tyto přihlašovací údaje ve vaší aplikaci.

Když nasadíte aplikace do hostitelského prostředí Azure, jako je virtuální počítač, můžete v tomto prostředí přiřadit spravovanou identitu. Pak nebudete muset zadávat přihlašovací údaje pro připojení ke službám Azure.

Poznámka:

Spravovaná identita poskytuje identitu zabezpečení, která představuje aplikaci nebo službu. Identitu spravuje platforma Azure a nevyžaduje, abyste zřizovali nebo rotovali tajné kódy. Další informace o spravovaných identitách najdete v přehledové dokumentaci.

Migrace existující aplikace pro použití připojení bez hesla

Následující postup vysvětluje, jak migrovat existující aplikaci tak, aby místo řešení SAS používala připojení bez hesla.

0) Příprava pracovního prostředí pro místní ověřování vývoje

Nejprve pomocí následujícího příkazu nastavte některé proměnné prostředí.

export AZ_RESOURCE_GROUP=<YOUR_RESOURCE_GROUP>
export AZ_EVENTHUBS_NAMESPACE_NAME=<YOUR_EVENTHUBS_NAMESPACE_NAME>
export AZ_EVENTHUB_NAME=<YOUR_EVENTHUB_NAME>

Zástupné symboly nahraďte následujícími hodnotami, které se používají v tomto článku:

  • <YOUR_RESOURCE_GROUP>: Název skupiny prostředků, kterou použijete.
  • <YOUR_EVENTHUBS_NAMESPACE_NAME>: Název oboru názvů služby Azure Event Hubs, který použijete.
  • <YOUR_EVENTHUB_NAME>: Název centra událostí, které budete používat.

1) Udělení oprávnění ke službě Azure Event Hubs

Pokud chcete tuto ukázku spustit místně s ověřováním Microsoft Entra, ujistěte se, že se váš uživatelský účet ověřil prostřednictvím sady Azure Toolkit for IntelliJ, modulu plug-in účtu Azure Pro Visual Studio Code nebo Azure CLI. Také se ujistěte, že účet má dostatečná oprávnění.

  1. Na webu Azure Portal vyhledejte obor názvů služby Event Hubs pomocí hlavního panelu hledání nebo levé navigace.

  2. Na stránce přehledu služby Event Hubs vyberte v nabídce vlevo řízení přístupu (IAM ).

  3. Na stránce Řízení přístupu (IAM) vyberte kartu Přiřazení rolí.

  4. V horní nabídce vyberte Přidat a potom přidejte přiřazení role z výsledné rozevírací nabídky.

    Screenshot of Azure portal Access Control (IAM) page of Event Hubs Namespace resource with Add role assignment highlighted.

  5. Pomocí vyhledávacího pole vyfiltrujte výsledky podle požadované role. V tomto příkladu vyhledejte odesílatele dat služby Azure Event Hubs a příjemce dat služby Azure Event Hubs a vyberte odpovídající výsledek a pak zvolte Další.

  6. V části Přiřadit přístup vyberte Uživatele, skupinu nebo instanční objekt a pak zvolte Vybrat členy.

  7. V dialogovém okně vyhledejte své uživatelské jméno Microsoft Entra (obvykle vaše user@domain e-mailová adresa) a pak v dolní části dialogového okna zvolte Vybrat .

  8. Vyberte Zkontrolovat a přiřadit přejděte na poslední stránku a pak proces dokončete opětovnou kontrolou a přiřazením .

Další informace o udělení přístupových rolí naleznete v tématu Autorizace přístupu k prostředkům služby Event Hubs pomocí Microsoft Entra ID.

2) Přihlaste se a migrujte kód aplikace tak, aby používal připojení bez hesla.

V případě místního vývoje se ujistěte, že jste ověřeni pomocí stejného účtu Microsoft Entra, ke kterému jste přiřadili roli ve službě Event Hubs. Ověřování můžete provést prostřednictvím Azure CLI, sady Visual Studio, Azure PowerShellu nebo jiných nástrojů, jako je IntelliJ.

Přihlaste se k Azure přes Azure CLI pomocí následujícího příkazu:

az login

Dále pomocí následujících kroků aktualizujte aplikaci Spring Kafka tak, aby používala připojení bez hesla. I když jsou koncepčně podobné, každá architektura používá různé podrobnosti implementace.

  1. V projektu otevřete soubor pom.xml a přidejte následující odkaz:

    <dependency>
       <groupId>com.azure</groupId>
       <artifactId>azure-identity</artifactId>
       <version>1.6.0</version>
    </dependency>
    
  2. Po migraci implementujte v projektu ověřování OAuth2 authenticateCallbackHandler a OAuthBearerToken , jak je znázorněno v následujícím příkladu.

    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();
        }
    }
    
  3. Při vytváření producenta nebo příjemce Kafka přidejte konfiguraci potřebnou k podpoře mechanismu SASL/OAUTHBEARER . Následující příklady ukazují, jak by měl váš kód vypadat před migrací a po migraci. V obou příkladech nahraďte <eventhubs-namespace> zástupný symbol názvem vašeho oboru názvů služby Event Hubs.

    Před migrací by váš kód měl vypadat jako v následujícím příkladu:

    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);
    

    Po migraci by měl váš kód vypadat jako v následujícím příkladu. V tomto příkladu <path-to-your-KafkaOAuth2AuthenticateCallbackHandler> nahraďte zástupný symbol úplným názvem třídy pro vaši implementovanou 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);
    

Místní spuštění aplikace

Po provedení těchto změn kódu spusťte aplikaci místně. Nová konfigurace by měla převzít vaše místní přihlašovací údaje za předpokladu, že jste přihlášeni k kompatibilnímu integrovanému vývojovému prostředí nebo nástroji příkazového řádku, jako je Azure CLI, Visual Studio nebo IntelliJ. Role, které jste přiřadili místnímu vývojovému uživateli v Azure, umožní vaší aplikaci připojit se ke službě Azure místně.

3) Konfigurace hostitelského prostředí Azure

Jakmile je vaše aplikace nakonfigurovaná tak, aby používala připojení bez hesla a běží místně, může se stejný kód po nasazení do Azure ověřit ve službách Azure. Například aplikace nasazená do instance Azure Spring Apps, která má přiřazenou spravovanou identitu, se může připojit ke službě Azure Event Hubs pro Kafka.

V této části provedete dva kroky, které vaší aplikaci umožní spouštět v hostitelském prostředí Azure bez hesla:

  • Přiřaďte spravovanou identitu pro hostitelské prostředí Azure.
  • Přiřaďte spravované identitě role.

Poznámka:

Azure také poskytuje service Připojení or, který vám může pomoct s propojením hostitelské služby se službou Event Hubs. Pomocí nástroje Service Připojení or pro konfiguraci hostitelského prostředí můžete vynechat krok přiřazování rolí spravované identitě, protože služba Připojení or to udělá za vás. Následující část popisuje, jak nakonfigurovat hostitelské prostředí Azure dvěma způsoby: jedno prostřednictvím služby Připojení or a druhé konfigurací každého hostitelského prostředí přímo.

Důležité

Příkazy služby Připojení or vyžadují Azure CLI 2.41.0 nebo vyšší.

Přiřazení spravované identity pro hostitelské prostředí Azure

Následující kroky ukazují, jak přiřadit spravovanou identitu přiřazenou systémem pro různé služby hostování webů. Spravovaná identita se může bezpečně připojit k jiným službám Azure pomocí konfigurací aplikací, které jste nastavili dříve.

  1. Na hlavní stránce přehledu vaší instance služby Aplikace Azure vyberte v navigačním podokně identitu.

  2. Na kartě Přiřazený systém nezapomeňte nastavit pole Stav na zapnuto. Identitu přiřazenou systémem spravuje Azure interně a zpracovává úlohy správy za vás. Podrobnosti a ID identity se ve vašem kódu nikdy nezpřístupní.

    Screenshot of Azure portal Identity page of App Service resource with System assigned tab showing and Status field highlighted.

Spravovanou identitu můžete také přiřadit v hostitelském prostředí Azure pomocí Azure CLI.

Spravovanou identitu můžete přiřadit instanci služby Aplikace Azure pomocí příkazu az webapp identity assign, jak je znázorněno v následujícím příkladu.

export AZURE_MANAGED_IDENTITY_ID=$(az webapp identity assign \
    --resource-group $AZ_RESOURCE_GROUP \
    --name <app-service-name> \
    --query principalId \
    --output tsv)

Přiřazení rolí ke spravované identitě

Dále udělte oprávnění spravované identitě, kterou jste vytvořili pro přístup k oboru názvů služby Event Hubs. Oprávnění můžete udělit přiřazením role spravované identitě stejně jako u místního vývojového uživatele.

Pokud jste služby připojili pomocí služby Připojení or, nemusíte tento krok dokončit. Za vás byly zpracovány následující nezbytné konfigurace:

  • Pokud jste při vytváření připojení vybrali spravovanou identitu přiřazenou systémem, vytvořila se pro vaši aplikaci spravovaná identita a přiřadila se jim role Odesílatele dat služby Azure Event Hubs a příjemce dat azure Event Hubs ve službě Event Hubs.

  • Pokud jste se rozhodli použít připojovací řetězec, připojovací řetězec se přidala jako proměnná prostředí aplikace.

Otestování aplikace

Po provedení těchto změn kódu přejděte v prohlížeči do hostované aplikace. Vaše aplikace by se měla úspěšně připojit ke službě Azure Event Hubs pro Kafka. Mějte na paměti, že rozšíření přiřazení rolí v prostředí Azure může trvat několik minut. Vaše aplikace je teď nakonfigurovaná tak, aby běžela místně i v produkčním prostředí, aniž by vývojáři museli spravovat tajné kódy v samotné aplikaci.

Další kroky

V tomto kurzu jste zjistili, jak migrovat aplikaci na připojení bez hesla.

Podrobnější informace o konceptech probíraných v tomto článku najdete v následujících zdrojích informací: