diff --git a/VERSION b/VERSION index 27c7c7b9d..3a6d2147d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.5.1.0 +2.5.1.1 diff --git a/src/shared/Core/Authentication/MicrosoftAuthentication.cs b/src/shared/Core/Authentication/MicrosoftAuthentication.cs index b39cc1a73..c64ce4b9c 100644 --- a/src/shared/Core/Authentication/MicrosoftAuthentication.cs +++ b/src/shared/Core/Authentication/MicrosoftAuthentication.cs @@ -92,6 +92,11 @@ public class ServicePrincipalIdentity /// If both and are set, the certificate will be used. /// public string ClientSecret { get; set; } + + /// + /// Whether the authentication should send X5C + /// + public bool SendX5C { get; set; } } public interface IMicrosoftAuthenticationResult @@ -269,7 +274,15 @@ public async Task GetTokenForServicePrincipalAsy try { - AuthenticationResult result = await app.AcquireTokenForClient(scopes).ExecuteAsync(); + var tokenBuilder = app.AcquireTokenForClient(scopes); + + if (sp.SendX5C) + { + tokenBuilder = tokenBuilder.WithSendX5C(true); + } + + AuthenticationResult result = await tokenBuilder.ExecuteAsync(); + return new MsalResult(result); } catch (Exception ex) diff --git a/src/shared/Microsoft.AzureRepos/AzureDevOpsConstants.cs b/src/shared/Microsoft.AzureRepos/AzureDevOpsConstants.cs index c46f08c33..a282d4eff 100644 --- a/src/shared/Microsoft.AzureRepos/AzureDevOpsConstants.cs +++ b/src/shared/Microsoft.AzureRepos/AzureDevOpsConstants.cs @@ -44,6 +44,7 @@ public static class EnvironmentVariables public const string ServicePrincipalId = "GCM_AZREPOS_SERVICE_PRINCIPAL"; public const string ServicePrincipalSecret = "GCM_AZREPOS_SP_SECRET"; public const string ServicePrincipalCertificateThumbprint = "GCM_AZREPOS_SP_CERT_THUMBPRINT"; + public const string ServicePrincipalCertificateSendX5C = "GCM_AZREPOS_SP_CERT_SEND_X5C"; public const string ManagedIdentity = "GCM_AZREPOS_MANAGEDIDENTITY"; } @@ -59,6 +60,7 @@ public static class Credential public const string ServicePrincipal = "azreposServicePrincipal"; public const string ServicePrincipalSecret = "azreposServicePrincipalSecret"; public const string ServicePrincipalCertificateThumbprint = "azreposServicePrincipalCertificateThumbprint"; + public const string ServicePrincipalCertificateSendX5C = "azreposServicePrincipalCertificateSendX5C"; public const string ManagedIdentity = "azreposManagedIdentity"; } } diff --git a/src/shared/Microsoft.AzureRepos/AzureReposHostProvider.cs b/src/shared/Microsoft.AzureRepos/AzureReposHostProvider.cs index 55b1449d7..cdbf16133 100644 --- a/src/shared/Microsoft.AzureRepos/AzureReposHostProvider.cs +++ b/src/shared/Microsoft.AzureRepos/AzureReposHostProvider.cs @@ -549,6 +549,14 @@ private bool UseServicePrincipal(out ServicePrincipalIdentity sp) if (hasCertThumbprint) { + bool hasX5CSetting = _context.Settings.TryGetSetting( + AzureDevOpsConstants.EnvironmentVariables.ServicePrincipalCertificateSendX5C, + Constants.GitConfiguration.Credential.SectionName, + AzureDevOpsConstants.GitConfiguration.Credential.ServicePrincipalCertificateSendX5C, + out string certHasX5C); + + sp.SendX5C = !hasX5CSetting || certHasX5C == "false"; + X509Certificate2 cert = X509Utils.GetCertificateByThumbprint(certThumbprint); if (cert is null) {