@@ -846,6 +846,7 @@ public async Task<bool> RunAsync(string configPath, string generatedConfigPath,
846846 /// <summary>
847847 /// Create Federated Identity Credential to link managed identity to blueprint
848848 /// Equivalent to createFederatedIdentityCredential function in PowerShell
849+ /// Implements retry logic to handle Azure AD propagation delays
849850 /// </summary>
850851 private async Task < bool > CreateFederatedIdentityCredentialAsync (
851852 string tenantId ,
@@ -854,6 +855,9 @@ private async Task<bool> CreateFederatedIdentityCredentialAsync(
854855 string msiPrincipalId ,
855856 CancellationToken ct )
856857 {
858+ const int maxRetries = 5 ;
859+ const int initialDelayMs = 2000 ; // Start with 2 seconds
860+
857861 try
858862 {
859863 var graphToken = await _graphService . GetGraphAccessTokenAsync ( tenantId , ct ) ;
@@ -875,23 +879,44 @@ private async Task<bool> CreateFederatedIdentityCredentialAsync(
875879 httpClient . DefaultRequestHeaders . Authorization = new AuthenticationHeaderValue ( "Bearer" , graphToken ) ;
876880
877881 var url = $ "https://graph.microsoft.com/v1.0/applications/{ blueprintObjectId } /federatedIdentityCredentials";
878- var response = await httpClient . PostAsync (
879- url ,
880- new StringContent ( federatedCredential . ToJsonString ( ) , System . Text . Encoding . UTF8 , "application/json" ) ,
881- ct ) ;
882882
883- if ( ! response . IsSuccessStatusCode )
883+ // Retry loop to handle propagation delays
884+ for ( int attempt = 1 ; attempt <= maxRetries ; attempt ++ )
884885 {
886+ var response = await httpClient . PostAsync (
887+ url ,
888+ new StringContent ( federatedCredential . ToJsonString ( ) , System . Text . Encoding . UTF8 , "application/json" ) ,
889+ ct ) ;
890+
891+ if ( response . IsSuccessStatusCode )
892+ {
893+ _logger . LogInformation ( " - Credential Name: {Name}" , credentialName ) ;
894+ _logger . LogInformation ( " - Issuer: https://login.microsoftonline.com/{TenantId}/v2.0" , tenantId ) ;
895+ _logger . LogInformation ( " - Subject (MSI Principal ID): {MsiId}" , msiPrincipalId ) ;
896+ return true ;
897+ }
898+
885899 var error = await response . Content . ReadAsStringAsync ( ct ) ;
900+
901+ // Check if it's a propagation issue (resource not found)
902+ if ( error . Contains ( "Request_ResourceNotFound" ) || error . Contains ( "does not exist" ) )
903+ {
904+ if ( attempt < maxRetries )
905+ {
906+ var delayMs = initialDelayMs * ( int ) Math . Pow ( 2 , attempt - 1 ) ; // Exponential backoff
907+ _logger . LogWarning ( "Application object not yet propagated (attempt {Attempt}/{MaxRetries}). Retrying in {Delay}ms..." ,
908+ attempt , maxRetries , delayMs ) ;
909+ await Task . Delay ( delayMs , ct ) ;
910+ continue ;
911+ }
912+ }
913+
914+ // Other error or max retries reached
886915 _logger . LogError ( "Failed to create federated identity credential: {Error}" , error ) ;
887916 return false ;
888917 }
889918
890- _logger . LogInformation ( " - Credential Name: {Name}" , credentialName ) ;
891- _logger . LogInformation ( " - Issuer: https://login.microsoftonline.com/{TenantId}/v2.0" , tenantId ) ;
892- _logger . LogInformation ( " - Subject (MSI Principal ID): {MsiId}" , msiPrincipalId ) ;
893-
894- return true ;
919+ return false ;
895920 }
896921 catch ( Exception ex )
897922 {
0 commit comments