in sdk/extensions/Microsoft.Extensions.Azure/src/Internal/ClientFactory.cs [94:302]
internal static TokenCredential CreateCredential(IConfiguration configuration)
{
var credentialType = configuration["credential"];
var clientId = configuration["clientId"];
var tenantId = configuration["tenantId"];
var serviceConnectionId = configuration["serviceConnectionId"];
var resourceId = configuration["managedIdentityResourceId"];
var objectId = configuration["managedIdentityObjectId"];
var clientSecret = configuration["clientSecret"];
var certificate = configuration["clientCertificate"];
var certificateStoreName = configuration["clientCertificateStoreName"];
var certificateStoreLocation = configuration["clientCertificateStoreLocation"];
var systemAccessToken = configuration["systemAccessToken"];
var additionallyAllowedTenants = configuration["additionallyAllowedTenants"];
var tokenFilePath = configuration["tokenFilePath"];
IEnumerable<string> additionallyAllowedTenantsList = null;
if (!string.IsNullOrWhiteSpace(additionallyAllowedTenants))
{
// not relying on StringSplitOptions.RemoveEmptyEntries as we want to remove leading/trailing whitespace between entries
additionallyAllowedTenantsList = additionallyAllowedTenants.Split(TenantDelimiter)
.Select(t => t.Trim())
.Where(t => t.Length > 0);
}
if (string.Equals(credentialType, "managedidentity", StringComparison.OrdinalIgnoreCase))
{
int idCount = 0;
idCount += string.IsNullOrWhiteSpace(clientId) ? 0 : 1;
idCount += string.IsNullOrWhiteSpace(resourceId) ? 0 : 1;
idCount += string.IsNullOrWhiteSpace(objectId) ? 0 : 1;
if (idCount > 1)
{
throw new ArgumentException("Only one of either 'clientId', 'managedIdentityResourceId', or 'managedIdentityObjectId' can be specified for managed identity.");
}
if (!string.IsNullOrWhiteSpace(resourceId))
{
return new ManagedIdentityCredential(new ResourceIdentifier(resourceId));
}
if (!string.IsNullOrWhiteSpace(objectId))
{
return new ManagedIdentityCredential(ManagedIdentityId.FromUserAssignedObjectId(objectId));
}
return new ManagedIdentityCredential(clientId);
}
if (string.Equals(credentialType, "workloadidentity", StringComparison.OrdinalIgnoreCase))
{
// The WorkloadIdentityCredentialOptions object initialization populates its instance members
// from the environment variables AZURE_TENANT_ID, AZURE_CLIENT_ID, and AZURE_FEDERATED_TOKEN_FILE
var workloadIdentityOptions = new WorkloadIdentityCredentialOptions();
if (!string.IsNullOrWhiteSpace(tenantId))
{
workloadIdentityOptions.TenantId = tenantId;
}
if (!string.IsNullOrWhiteSpace(clientId))
{
workloadIdentityOptions.ClientId = clientId;
}
if (!string.IsNullOrWhiteSpace(tokenFilePath))
{
workloadIdentityOptions.TokenFilePath = tokenFilePath;
}
if (additionallyAllowedTenantsList != null)
{
foreach (string tenant in additionallyAllowedTenantsList)
{
workloadIdentityOptions.AdditionallyAllowedTenants.Add(tenant);
}
}
if (!string.IsNullOrWhiteSpace(workloadIdentityOptions.TenantId) &&
!string.IsNullOrWhiteSpace(workloadIdentityOptions.ClientId) &&
!string.IsNullOrWhiteSpace(workloadIdentityOptions.TokenFilePath))
{
return new WorkloadIdentityCredential(workloadIdentityOptions);
}
throw new ArgumentException("For workload identity, 'tenantId', 'clientId', and 'tokenFilePath' must be specified via environment variables or the configuration.");
}
if (string.Equals(credentialType, "azurepipelines", StringComparison.OrdinalIgnoreCase))
{
if (string.IsNullOrWhiteSpace(tenantId) ||
string.IsNullOrWhiteSpace(clientId) ||
string.IsNullOrWhiteSpace(serviceConnectionId) ||
string.IsNullOrWhiteSpace(systemAccessToken))
{
throw new ArgumentException("For Azure Pipelines, 'tenantId', 'clientId', 'serviceConnectionId', and 'systemAccessToken' must be specified via the configuration.");
}
var options = new AzurePipelinesCredentialOptions();
if (additionallyAllowedTenantsList != null)
{
foreach (string tenant in additionallyAllowedTenantsList)
{
options.AdditionallyAllowedTenants.Add(tenant);
}
}
return new AzurePipelinesCredential(tenantId, clientId, serviceConnectionId, systemAccessToken, options);
}
if (!string.IsNullOrWhiteSpace(tenantId) &&
!string.IsNullOrWhiteSpace(clientId) &&
!string.IsNullOrWhiteSpace(clientSecret))
{
var options = new ClientSecretCredentialOptions();
if (additionallyAllowedTenantsList != null)
{
foreach (string tenant in additionallyAllowedTenantsList)
{
options.AdditionallyAllowedTenants.Add(tenant);
}
}
return new ClientSecretCredential(tenantId, clientId, clientSecret, options);
}
if (!string.IsNullOrWhiteSpace(tenantId) &&
!string.IsNullOrWhiteSpace(clientId) &&
!string.IsNullOrWhiteSpace(certificate))
{
StoreLocation storeLocation = StoreLocation.CurrentUser;
if (!string.IsNullOrWhiteSpace(certificateStoreLocation))
{
storeLocation = (StoreLocation)Enum.Parse(typeof(StoreLocation), certificateStoreLocation, true);
}
if (string.IsNullOrWhiteSpace(certificateStoreName))
{
certificateStoreName = "MY"; // MY is the default used in X509Store
}
using var store = new X509Store(certificateStoreName, storeLocation);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindByThumbprint, certificate, false);
if (certs.Count == 0)
{
throw new InvalidOperationException($"Unable to find a certificate with thumbprint '{certificate}'");
}
var options = new ClientCertificateCredentialOptions();
if (additionallyAllowedTenantsList != null)
{
foreach (string tenant in additionallyAllowedTenantsList)
{
options.AdditionallyAllowedTenants.Add(tenant);
}
}
var credential = new ClientCertificateCredential(tenantId, clientId, certs[0], options);
store.Close();
return credential;
}
// TODO: More logging
if (!string.IsNullOrWhiteSpace(objectId))
{
throw new ArgumentException("'managedIdentityObjectId' is only supported when the credential type is 'managedidentity'.");
}
if (additionallyAllowedTenantsList != null
|| !string.IsNullOrWhiteSpace(tenantId)
|| !string.IsNullOrWhiteSpace(clientId)
|| !string.IsNullOrWhiteSpace(resourceId))
{
var options = new DefaultAzureCredentialOptions();
if (additionallyAllowedTenantsList != null)
{
foreach (string tenant in additionallyAllowedTenantsList)
{
options.AdditionallyAllowedTenants.Add(tenant);
}
}
if (!string.IsNullOrWhiteSpace(tenantId))
{
options.TenantId = tenantId;
}
if (!string.IsNullOrWhiteSpace(clientId))
{
options.ManagedIdentityClientId = clientId;
}
// validation that both clientId and ResourceId are not set happens in Azure.Identity
if (!string.IsNullOrWhiteSpace(resourceId))
{
options.ManagedIdentityResourceId = new ResourceIdentifier(resourceId);
}
return new DefaultAzureCredential(options);
}
return null;
}