Aracılığıyla paylaş


Azure hizmetlerine erişmek için Service Fabric uygulamasının yönetilen kimliğinden yararlanma

Service Fabric uygulamaları, Microsoft Entra Id tabanlı kimlik doğrulamasını destekleyen diğer Azure kaynaklarına erişmek için yönetilen kimlikleri kullanabilir. Bir uygulama, sistem tarafından atanmış veya kullanıcı tarafından atanmış olabilecek kimliğini temsil eden bir erişim belirteci alabilir ve korumalı kaynak sunucusu olarak da bilinen başka bir hizmette kimliğini doğrulamak için bunu 'taşıyıcı' belirteç olarak kullanabilir. Belirteç, Service Fabric uygulamasına atanan kimliği temsil eder ve yalnızca bu kimliği paylaşan Azure kaynaklarına (SF uygulamaları dahil) verilir. Yönetilen kimliklerin ayrıntılı açıklamasının yanı sıra sistem tarafından atanan ve kullanıcı tarafından atanan kimlikler arasındaki ayrım için yönetilen kimliğe genel bakış belgelerine bakın. Bu makale boyunca istemci uygulaması olarak yönetilen kimlik özellikli bir Service Fabric uygulamasına başvuracağız.

Reliable Services ve kapsayıcılarla sistem tarafından atanan ve kullanıcı tarafından atanan Service Fabric uygulaması yönetilen kimliklerinin kullanılmasını gösteren yardımcı örnek uygulamaya bakın.

Önemli

Yönetilen kimlik, kaynağı içeren abonelikle ilişkilendirilmiş ilgili Microsoft Entra kiracısında bir Azure kaynağı ile hizmet sorumlusu arasındaki ilişkiyi temsil eder. Bu nedenle, Service Fabric bağlamında yönetilen kimlikler yalnızca Azure kaynakları olarak dağıtılan uygulamalar için desteklenir.

Önemli

Service Fabric uygulamasının yönetilen kimliğini kullanmadan önce, istemci uygulamaya korumalı kaynağa erişim verilmelidir. Destek olup olmadığını denetlemek için Microsoft Entra kimlik doğrulamasını destekleyen Azure hizmetlerinin listesine ve ardından ilgilendiğiniz kaynaklara kimlik erişimi vermek için belirli adımlar için ilgili hizmetin belgelerine bakın.

Azure.Identity kullanarak yönetilen kimlik kullanma

Azure Kimlik SDK'sı artık Service Fabric'i destekliyor. Azure.Identity kullanmak, Service Fabric uygulaması tarafından yönetilen kimlikleri kullanmak için kod yazmayı kolaylaştırır çünkü belirteçleri getirme, belirteçleri önbelleğe alma ve sunucu kimlik doğrulamasını işler. Azure kaynaklarının çoğuna erişilirken belirteç kavramı gizlenir.

Service Fabric desteği, bu diller için aşağıdaki sürümlerde kullanılabilir:

Azure Key Vault'tan gizli dizi getirmek için kimlik bilgilerini başlatmaya ve kimlik bilgilerini kullanmaya ilişkin C# örneği:

using Azure.Identity;
using Azure.Security.KeyVault.Secrets;

namespace MyMIService
{
    internal sealed class MyMIService : StatelessService
    {
        protected override async Task RunAsync(CancellationToken cancellationToken)
        {
            try
            {
                // Load the service fabric application managed identity assigned to the service
                ManagedIdentityCredential creds = new ManagedIdentityCredential();

                // Create a client to keyvault using that identity
                SecretClient client = new SecretClient(new Uri("https://mykv.vault.azure.net/"), creds);

                // Fetch a secret
                KeyVaultSecret secret = (await client.GetSecretAsync("mysecret", cancellationToken: cancellationToken)).Value;
            }
            catch (CredentialUnavailableException e)
            {
                // Handle errors with loading the Managed Identity
            }
            catch (RequestFailedException)
            {
                // Handle errors with fetching the secret
            }
            catch (Exception e)
            {
                // Handle generic errors
            }
        }
    }
}

REST API kullanarak erişim belirteci alma

Yönetilen kimlik için etkinleştirilmiş kümelerde Service Fabric çalışma zamanı, uygulamaların erişim belirteçlerini almak için kullanabileceği bir localhost uç noktasını kullanıma sunar. Uç nokta, kümenin her düğümünde kullanılabilir ve bu düğümdeki tüm varlıklar tarafından erişilebilir. Yetkili arayanlar bu uç noktayı çağırarak ve bir kimlik doğrulama kodu sunarak erişim belirteçleri alabilir; kod, her ayrı hizmet kodu paketi etkinleştirmesi için Service Fabric çalışma zamanı tarafından oluşturulur ve bu hizmet kodu paketini barındıran işlemin ömrüne bağlıdır.

Özellikle, yönetilen kimlik özellikli service Fabric hizmetinin ortamı aşağıdaki değişkenlerle dağıtılır:

  • 'IDENTITY_ENDPOINT': hizmetin yönetilen kimliğine karşılık gelen localhost uç noktası
  • 'IDENTITY_HEADER': geçerli düğümdeki hizmeti temsil eden benzersiz bir kimlik doğrulama kodu
  • 'IDENTITY_SERVER_THUMBPRINT': Service Fabric yönetilen kimlik sunucusunun parmak izi

Önemli

Uygulama kodu , 'IDENTITY_HEADER' ortam değişkeninin değerini hassas veriler olarak dikkate almalıdır; günlüğe kaydedilmemeli veya başka bir şekilde dağıtılmamalıdır. Kimlik doğrulama kodunun yerel düğüm dışında veya hizmeti barındıran işlem sonlandırıldıktan sonra değeri yoktur, ancak Service Fabric hizmetinin kimliğini temsil eder ve bu nedenle erişim belirtecinin kendisiyle aynı önlemlerle ele alınmalıdır.

Belirteç almak için istemci aşağıdaki adımları gerçekleştirir:

  • yönetilen kimlik uç noktasını (IDENTITY_ENDPOINT değer) API sürümü ve belirteç için gereken kaynak (hedef kitle) ile birleştirerek bir URI oluşturur
  • belirtilen URI için bir GET http(s) isteği oluşturur
  • uygun sunucu sertifikası doğrulama mantığı ekler
  • kimlik doğrulama kodunu (IDENTITY_HEADER değer) isteğe üst bilgi olarak ekler
  • isteği gönderir

Başarılı bir yanıt, sonuçta elde edilen erişim belirtecini ve bunu açıklayan meta verileri temsil eden bir JSON yükü içerir. Başarısız yanıt, hatanın açıklamasını da içerir. Hata işleme hakkında ek ayrıntılar için aşağıya bakın.

Erişim belirteçleri Service Fabric tarafından çeşitli düzeylerde (düğüm, küme, kaynak sağlayıcısı hizmeti) önbelleğe alınır, bu nedenle başarılı bir yanıt, belirtecin kullanıcı uygulamasının isteğine doğrudan yanıt olarak verildiği anlamına gelmez. Belirteçler kullanım ömründen daha kısa bir süre boyunca önbelleğe alınır ve bu nedenle uygulamanın geçerli bir belirteç alması garanti edilir. Uygulama kodunun aldığı tüm erişim belirteçlerini önbelleğe alması önerilir; önbelleğe alma anahtarı hedef kitleyi içermelidir (bir türetme).

Örnek istek:

GET 'https://localhost:2377/metadata/identity/oauth2/token?api-version=2019-07-01-preview&resource=https://vault.azure.net/' HTTP/1.1 Secret: 912e4af7-77ba-4fa5-a737-56c8e3ace132

konumu:

Öğe Tanım
GET Uç noktadan veri almak istediğinizi belirten HTTP fiili. Bu durumda, bir OAuth erişim belirteci.
https://localhost:2377/metadata/identity/oauth2/token IDENTITY_ENDPOINT ortam değişkeni aracılığıyla sağlanan Service Fabric uygulamaları için yönetilen kimlik uç noktası.
api-version Yönetilen Kimlik Belirteci Hizmeti'nin API sürümünü belirten bir sorgu dizesi parametresi; şu anda kabul edilen tek değer olan 2019-07-01-previewve değiştirilebilir.
resource Hedef kaynağın Uygulama Kimliği URI'sini gösteren bir sorgu dizesi parametresi. Bu, verilen belirtecin aud (hedef kitle) talebi olarak yansıtılır. Bu örnek, Uygulama Kimliği URI'si olan Azure Key Vault'a erişmek için bir belirteç istemektedir https://vault.azure.net/.
Secret Çağıranın kimliğini doğrulamak için Service Fabric hizmetleri için Service Fabric Yönetilen Kimlik Belirteci Hizmeti tarafından gereken bir HTTP isteği üst bilgisi alanı. Bu değer, IDENTITY_HEADER ortam değişkeni aracılığıyla SF çalışma zamanı tarafından sağlanır.

Örnek yanıt:

HTTP/1.1 200 OK
Content-Type: application/json
{
    "token_type":  "Bearer",
    "access_token":  "eyJ0eXAiO...",
    "expires_on":  1565244611,
    "resource":  "https://vault.azure.net/"
}

konumu:

Öğe Tanım
token_type Belirtecin türü; bu durumda, bu belirtecin sunucusu ('taşıyıcı') belirtecin hedeflenen konusu olduğu anlamına gelen bir "Taşıyıcı" erişim belirtecidir.
access_token İstenen erişim belirteci. Güvenli bir REST API çağrılırken, belirteç istek üst bilgisi alanına "taşıyıcı" belirteç olarak eklenir Authorization ve API'nin çağıranın kimliğini doğrulamasına olanak sağlar.
expires_on Erişim belirtecinin süre sonunun zaman damgası; "1970-01-01T0:0:0Z UTC" arasındaki saniye sayısı olarak temsil edilir ve belirtecin exp talebine karşılık gelir. Bu durumda belirtecin süresi 2019-08-08T06:10:11+00:00 tarihinde dolar (RFC 3339'da)
resource erişim belirtecinin verildiği kaynak, isteğin resource sorgu dizesi parametresiyle belirtilir; belirtecin 'aud' talebine karşılık gelir.

C kullanarak erişim belirteci alma#

Yukarıdaki C# dilinde olur:

namespace Azure.ServiceFabric.ManagedIdentity.Samples
{
    using System;
    using System.Net.Http;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Web;
    using Newtonsoft.Json;

    /// <summary>
    /// Type representing the response of the SF Managed Identity endpoint for token acquisition requests.
    /// </summary>
    [JsonObject]
    public sealed class ManagedIdentityTokenResponse
    {
        [JsonProperty(Required = Required.Always, PropertyName = "token_type")]
        public string TokenType { get; set; }

        [JsonProperty(Required = Required.Always, PropertyName = "access_token")]
        public string AccessToken { get; set; }

        [JsonProperty(PropertyName = "expires_on")]
        public string ExpiresOn { get; set; }

        [JsonProperty(PropertyName = "resource")]
        public string Resource { get; set; }
    }

    /// <summary>
    /// Sample class demonstrating access token acquisition using Managed Identity.
    /// </summary>
    public sealed class AccessTokenAcquirer
    {
        /// <summary>
        /// Acquire an access token.
        /// </summary>
        /// <returns>Access token</returns>
        public static async Task<string> AcquireAccessTokenAsync()
        {
            var managedIdentityEndpoint = Environment.GetEnvironmentVariable("IDENTITY_ENDPOINT");
            var managedIdentityAuthenticationCode = Environment.GetEnvironmentVariable("IDENTITY_HEADER");
            var managedIdentityServerThumbprint = Environment.GetEnvironmentVariable("IDENTITY_SERVER_THUMBPRINT");
            // Latest api version, 2019-07-01-preview is still supported.
            var managedIdentityApiVersion = Environment.GetEnvironmentVariable("IDENTITY_API_VERSION");
            var managedIdentityAuthenticationHeader = "secret";
            var resource = "https://management.azure.com/";

            var requestUri = $"{managedIdentityEndpoint}?api-version={managedIdentityApiVersion}&resource={HttpUtility.UrlEncode(resource)}";

            var requestMessage = new HttpRequestMessage(HttpMethod.Get, requestUri);
            requestMessage.Headers.Add(managedIdentityAuthenticationHeader, managedIdentityAuthenticationCode);
            
            var handler = new HttpClientHandler();
            handler.ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, certChain, policyErrors) =>
            {
                // Do any additional validation here
                if (policyErrors == SslPolicyErrors.None)
                {
                    return true;
                }
                return 0 == string.Compare(cert.GetCertHashString(), managedIdentityServerThumbprint, StringComparison.OrdinalIgnoreCase);
            };

            try
            {
                var response = await new HttpClient(handler).SendAsync(requestMessage)
                    .ConfigureAwait(false);

                response.EnsureSuccessStatusCode();

                var tokenResponseString = await response.Content.ReadAsStringAsync()
                    .ConfigureAwait(false);

                var tokenResponseObject = JsonConvert.DeserializeObject<ManagedIdentityTokenResponse>(tokenResponseString);

                return tokenResponseObject.AccessToken;
            }
            catch (Exception ex)
            {
                string errorText = String.Format("{0} \n\n{1}", ex.Message, ex.InnerException != null ? ex.InnerException.Message : "Acquire token failed");

                Console.WriteLine(errorText);
            }

            return String.Empty;
        }
    } // class AccessTokenAcquirer
} // namespace Azure.ServiceFabric.ManagedIdentity.Samples

Yönetilen Kimlik kullanarak Service Fabric uygulamasından Key Vault'a erişme

Bu örnek, yönetilen kimlik kullanarak Key Vault'ta depolanan bir gizli diziye erişimi göstermek için yukarıdakileri temel alır.

        /// <summary>
        /// Probe the specified secret, displaying metadata on success.  
        /// </summary>
        /// <param name="vault">vault name</param>
        /// <param name="secret">secret name</param>
        /// <param name="version">secret version id</param>
        /// <returns></returns>
        public async Task<string> ProbeSecretAsync(string vault, string secret, string version)
        {
            // initialize a KeyVault client with a managed identity-based authentication callback
            var kvClient = new Microsoft.Azure.KeyVault.KeyVaultClient(new Microsoft.Azure.KeyVault.KeyVaultClient.AuthenticationCallback((a, r, s) => { return AuthenticationCallbackAsync(a, r, s); }));

            Log(LogLevel.Info, $"\nRunning with configuration: \n\tobserved vault: {config.VaultName}\n\tobserved secret: {config.SecretName}\n\tMI endpoint: {config.ManagedIdentityEndpoint}\n\tMI auth code: {config.ManagedIdentityAuthenticationCode}\n\tMI auth header: {config.ManagedIdentityAuthenticationHeader}");
            string response = String.Empty;

            Log(LogLevel.Info, "\n== {DateTime.UtcNow.ToString()}: Probing secret...");
            try
            {
                var secretResponse = await kvClient.GetSecretWithHttpMessagesAsync(vault, secret, version)
                    .ConfigureAwait(false);

                if (secretResponse.Response.IsSuccessStatusCode)
                {
                    // use the secret: secretValue.Body.Value;
                    response = String.Format($"Successfully probed secret '{secret}' in vault '{vault}': {PrintSecretBundleMetadata(secretResponse.Body)}");
                }
                else
                {
                    response = String.Format($"Non-critical error encountered retrieving secret '{secret}' in vault '{vault}': {secretResponse.Response.ReasonPhrase} ({secretResponse.Response.StatusCode})");
                }
            }
            catch (Microsoft.Rest.ValidationException ve)
            {
                response = String.Format($"encountered REST validation exception 0x{ve.HResult.ToString("X")} trying to access '{secret}' in vault '{vault}' from {ve.Source}: {ve.Message}");
            }
            catch (KeyVaultErrorException kvee)
            {
                response = String.Format($"encountered KeyVault exception 0x{kvee.HResult.ToString("X")} trying to access '{secret}' in vault '{vault}': {kvee.Response.ReasonPhrase} ({kvee.Response.StatusCode})");
            }
            catch (Exception ex)
            {
                // handle generic errors here
                response = String.Format($"encountered exception 0x{ex.HResult.ToString("X")} trying to access '{secret}' in vault '{vault}': {ex.Message}");
            }

            Log(LogLevel.Info, response);

            return response;
        }

        /// <summary>
        /// KV authentication callback, using the application's managed identity.
        /// </summary>
        /// <param name="authority">The expected issuer of the access token, from the KV authorization challenge.</param>
        /// <param name="resource">The expected audience of the access token, from the KV authorization challenge.</param>
        /// <param name="scope">The expected scope of the access token; not currently used.</param>
        /// <returns>Access token</returns>
        public async Task<string> AuthenticationCallbackAsync(string authority, string resource, string scope)
        {
            Log(LogLevel.Verbose, $"authentication callback invoked with: auth: {authority}, resource: {resource}, scope: {scope}");
            var encodedResource = HttpUtility.UrlEncode(resource);

            // This sample does not illustrate the caching of the access token, which the user application is expected to do.
            // For a given service, the caching key should be the (encoded) resource uri. The token should be cached for a period
            // of time at most equal to its remaining validity. The 'expires_on' field of the token response object represents
            // the number of seconds from Unix time when the token will expire. You may cache the token if it will be valid for at
            // least another short interval (1-10s). If its expiration will occur shortly, don't cache but still return it to the 
            // caller. The MI endpoint will not return an expired token.
            // Sample caching code:
            //
            // ManagedIdentityTokenResponse tokenResponse;
            // if (responseCache.TryGetCachedItem(encodedResource, out tokenResponse))
            // {
            //     Log(LogLevel.Verbose, $"cache hit for key '{encodedResource}'");
            //
            //     return tokenResponse.AccessToken;
            // }
            //
            // Log(LogLevel.Verbose, $"cache miss for key '{encodedResource}'");
            //
            // where the response cache is left as an exercise for the reader. MemoryCache is a good option, albeit not yet available on .net core.

            var requestUri = $"{config.ManagedIdentityEndpoint}?api-version={config.ManagedIdentityApiVersion}&resource={encodedResource}";
            Log(LogLevel.Verbose, $"request uri: {requestUri}");

            var requestMessage = new HttpRequestMessage(HttpMethod.Get, requestUri);
            requestMessage.Headers.Add(config.ManagedIdentityAuthenticationHeader, config.ManagedIdentityAuthenticationCode);
            Log(LogLevel.Verbose, $"added header '{config.ManagedIdentityAuthenticationHeader}': '{config.ManagedIdentityAuthenticationCode}'");

            var response = await httpClient.SendAsync(requestMessage)
                .ConfigureAwait(false);
            Log(LogLevel.Verbose, $"response status: success: {response.IsSuccessStatusCode}, status: {response.StatusCode}");

            response.EnsureSuccessStatusCode();

            var tokenResponseString = await response.Content.ReadAsStringAsync()
                .ConfigureAwait(false);

            var tokenResponse = JsonConvert.DeserializeObject<ManagedIdentityTokenResponse>(tokenResponseString);
            Log(LogLevel.Verbose, "deserialized token response; returning access code..");

            // Sample caching code (continuation):
            // var expiration = DateTimeOffset.FromUnixTimeSeconds(Int32.Parse(tokenResponse.ExpiresOn));
            // if (expiration > DateTimeOffset.UtcNow.AddSeconds(5.0))
            //    responseCache.AddOrUpdate(encodedResource, tokenResponse, expiration);

            return tokenResponse.AccessToken;
        }

        private string PrintSecretBundleMetadata(SecretBundle bundle)
        {
            StringBuilder strBuilder = new StringBuilder();

            strBuilder.AppendFormat($"\n\tid: {bundle.Id}\n");
            strBuilder.AppendFormat($"\tcontent type: {bundle.ContentType}\n");
            strBuilder.AppendFormat($"\tmanaged: {bundle.Managed}\n");
            strBuilder.AppendFormat($"\tattributes:\n");
            strBuilder.AppendFormat($"\t\tenabled: {bundle.Attributes.Enabled}\n");
            strBuilder.AppendFormat($"\t\tnbf: {bundle.Attributes.NotBefore}\n");
            strBuilder.AppendFormat($"\t\texp: {bundle.Attributes.Expires}\n");
            strBuilder.AppendFormat($"\t\tcreated: {bundle.Attributes.Created}\n");
            strBuilder.AppendFormat($"\t\tupdated: {bundle.Attributes.Updated}\n");
            strBuilder.AppendFormat($"\t\trecoveryLevel: {bundle.Attributes.RecoveryLevel}\n");

            return strBuilder.ToString();
        }

        private enum LogLevel
        {
            Info,
            Verbose
        };

        private void Log(LogLevel level, string message)
        {
            if (level != LogLevel.Verbose
                || config.DoVerboseLogging)
            {
                Console.WriteLine(message);
            }
        }

Hata işleme

HTTP yanıt üst bilgisinin 'durum kodu' alanı isteğin başarı durumunu gösterir; '200 Tamam' durumu başarılı olduğunu gösterir ve yanıt, yukarıda açıklandığı gibi erişim belirtecini içerir. Olası hata yanıtlarının kısa bir numaralandırması aşağıdadır.

Durum Kodu Hata Nedeni nasıl işlenir
404 Bulunamadı. Bilinmeyen kimlik doğrulama kodu veya uygulamaya yönetilen kimlik atanmadı. Uygulama kurulumunu veya belirteç alma kodunu düzeltin.
429 Çok fazla istek var. Microsoft Entra Id veya SF tarafından uygulanan kısıtlama sınırına ulaşıldı. Üstel Geri Alma ile yeniden deneyin. Aşağıdaki yönergelere bakın.
İstekte 4xx Hatası. İstek parametrelerinden biri veya daha fazlası yanlıştı. Yeniden denemeyin. Daha fazla bilgi için hata ayrıntılarını inceleyin. 4xx hataları tasarım zamanı hatalarıdır.
5xx Hizmet hatası. Yönetilen kimlik alt sistemi veya Microsoft Entra Id geçici bir hata döndürdü. Kısa bir süre sonra yeniden denemek güvenlidir. Yeniden denemeden sonra bir azaltma koşuluna (429) basabilirsiniz.

Hata oluşursa, ilgili HTTP yanıt gövdesi hata ayrıntılarını içeren bir JSON nesnesi içerir:

Öğe Tanım
kod Hata kodu.
correlationId Hata ayıklama için kullanılabilecek bağıntı kimliği.
ileti Hatanın ayrıntılı açıklaması. Hata açıklamaları istediğiniz zaman değişebilir. Hata iletisinin kendisine bağlı değildir.

Örnek hata:

{"error":{"correlationId":"7f30f4d3-0f3a-41e0-a417-527f21b3848f","code":"SecretHeaderNotFound","message":"Secret is not found in the request headers."}}

Yönetilen kimliklere özgü tipik Service Fabric hatalarının listesi aşağıda verilmiştir:

Kod Mesaj Tanım
SecretHeaderNotFound İstek üst bilgilerinde gizli dizi bulunamadı. kimlik doğrulama kodu istekle birlikte sağlanmadı.
ManagedIdentityNotFound Belirtilen uygulama konağı için yönetilen kimlik bulunamadı. Uygulamanın kimliği yok veya kimlik doğrulama kodu bilinmiyor.
ArgumentNullOrEmpty 'resource' parametresi null veya boş dize olmamalıdır. Kaynak (hedef kitle) istekte sağlanmadı.
InvalidApiVersion '' api sürümü desteklenmiyor. Desteklenen sürüm: '2019-07-01-preview'. İstek URI'sinde belirtilen eksik veya desteklenmeyen API sürümü.
InternalServerError Bir hata oluşmuştur. Yönetilen kimlik alt sisteminde, büyük olasılıkla Service Fabric yığınının dışında bir hatayla karşılaşıldı. Büyük olasılıkla kaynak için yanlış bir değer belirtilmiştir (sonunda '/' olup olmadığını denetleyin)

Yeniden deneme kılavuzu

Genellikle yeniden denenebilir tek hata kodu 429'dur (Çok Fazla İstek Var); iç sunucu hataları/5xx hata kodları yeniden denenebilir, ancak nedeni kalıcı olabilir.

Azaltma sınırları, yönetilen kimlik alt sistemine yapılan çağrı sayısı (özellikle 'yukarı akış' bağımlılıkları (Yönetilen Kimlik Azure hizmeti veya güvenli belirteç hizmeti) için geçerlidir. Service Fabric, belirteçleri işlem hattındaki çeşitli düzeylerde önbelleğe alır, ancak ilgili bileşenlerin dağıtılmış yapısı göz önüne alındığında, çağıran tutarsız azaltma yanıtları yaşayabilir (örneğin, bir uygulamanın bir düğümünde/örneğinde kısıtlanabilir, ancak aynı kimlik için belirteç isterken farklı bir düğümde kullanılamaz.) Azaltma koşulu ayarlandığında, koşul temizlenene kadar aynı uygulamadan gelen sonraki istekler HTTP durum kodu 429 (Çok Fazla İstek) ile başarısız olabilir.

Azaltma nedeniyle başarısız olan isteklerin aşağıdaki gibi üstel geri alma ile yeniden denenmesi önerilir:

Çağrı dizini 429 alma eylemi
Kategori 1 1 saniye bekleyin ve yeniden deneyin
2 2 saniye bekleyin ve yeniden deneyin
3 4 saniye bekleyin ve yeniden deneyin
4 8 saniye bekleyin ve yeniden deneyin
4 8 saniye bekleyin ve yeniden deneyin
5 16 saniye bekleyin ve yeniden deneyin

Azure hizmetleri için kaynak kimlikleri

Microsoft Entra Kimliğini ve ilgili kaynak kimliklerini destekleyen kaynakların listesi için bkz . Microsoft Entra kimlik doğrulamasını destekleyen Azure hizmetleri.

Sonraki adımlar