我正在研究一种当前在Azure Functions中运行代码的解决方案。这些功能使用MSI身份验证已验证到我们的PaaS服务(Key Vault /服务总线/ Blob存储等)。
然后进行身份验证的代码如下:
// Connect to KeyVault in the context of the running code.
var tokenProvider = new AzureServiceTokenProvider();
var config = new ConfigurationBuilder().AddAzureKeyVault(
keyvaultUri,
new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(tokenProvider.KeyVaultTokenCallback)),
new DefaultKeyVaultSecretManager())
.Build();
然后,我可以使用以下代码安全地连接到Service Bus:
// Get ServiceBus connection settings.
config.GetSection("Messaging").Bind(ConfigSettings);
var namespaceName = Regex.Match(ConfigSettings.ConnectionString, @"Endpoint=sb:\/\/([^.]*)", RegexOptions.IgnoreCase).Groups[1].Value;
var token = tokenProvider.GetAccessTokenAsync("https://management.core.windows.net/", string.Empty).Result;
var tokenCredentials = new TokenCredentials(token);
var client = RestClient.Configure()
.WithEnvironment(AzureEnvironment.AzureGlobalCloud)
.WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
.WithCredentials(new AzureCredentials(tokenCredentials, tokenCredentials, string.Empty, AzureEnvironment.AzureGlobalCloud))
.Build();
// Authenticate against Service Bus.
ServiceBusNamespace = Azure.Authenticate(client, string.Empty)
.WithSubscription(ConfigSettings.SubscriptionId)
.ServiceBusNamespaces.List()
.SingleOrDefault(n => n.Name == namespaceName);
我们正在更改解决方案,以便代替在ASE上运行Functions,而要在Console App(在Linux上运行)中执行相同的操作。显然,MSI身份验证在这种情况下不起作用,因此我一直在使用Service Priniple AppId和AppSercret。我在AAD中设置了“原则”,如下所示:
使用此服务原则AppId和AppSecret的代码如下:
public async static Task<string> GetAccessToken(string tenantId, string appId, string appSecret)
{
var authenticationContext = new AuthenticationContext($"https://login.windows.net/{tenantId}");
var credential = new ClientCredential(clientId: appId, clientSecret: appSecret);
var result = await authenticationContext.AcquireTokenAsync(resource: "https://management.core.windows.net/", clientCredential: credential);
if (result == null) {
throw new InvalidOperationException("Failed to obtain the JWT token");
}
return result.AccessToken;
}
但它要求我保留AppId,AppSecret和TenantId之类的东西,以供应用程序使用。出于明显的安全原因,我不想使用AppSettings。
我现在可以使用与以前相似的代码运行服务总线身份验证:
var namespaceName = Regex.Match(connectionString, @"Endpoint=sb:\/\/([^.]*)", RegexOptions.IgnoreCase).Groups[1].Value;
var tokenCredentials = new TokenCredentials(token);
var client = RestClient.Configure()
.WithEnvironment(AzureEnvironment.AzureGlobalCloud)
.WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
.WithCredentials(new AzureCredentials(tokenCredentials, tokenCredentials, string.Empty, AzureEnvironment.AzureGlobalCloud))
.Build();
var serviceBusNamespace = Azure.Authenticate(client, string.Empty)
.WithSubscription(subscriptionId)
.ServiceBusNamespaces.List()
.SingleOrDefault(n => n.Name == namespaceName);
if (serviceBusNamespace == null)
{
throw new InvalidOperationException($"Couldn't find the service bus namespace {namespaceName} in the subscription with ID {subscriptionId}");
}
我的问题-担心安全性然后将所需的配置字段(AppId,AppSecret,TenantId)存储在config或Env Vars中似乎适得其反。我还有其他选择吗?除非已通过身份验证,否则我无法使用KeyVault,但再次需要经过身份验证的服务原则才能访问它。
以前有人做过这种方法吗?也许服务原则不是正确的方法?
在此先感谢任何指针!
答案 0 :(得分:1)
根据您的描述,您不想将AppId
存储在配置文件中,并希望使用Service Principle
进行身份验证。
如果是这样,您可以参考juunas文章,并可以使用AzureServiceTokenProvider
进行身份验证并继续进行所需的操作。
您可以使用以下代码来获取密钥库机密,而无需使用AppId
和AppSecret
。
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
var scret = keyVaultClient.GetSecretAsync("https://xxxx.vault.azure.net", "xxxx").GetAwaiter().GetResult();