【发布时间】:2021-05-05 09:20:35
【问题描述】:
我正在尝试为存储 blob 创建一个 SAS 令牌。我使用使用 MSI(托管服务标识)创建的 StorageCredentials 来创建 CloudBlobClient。创建 SAS 时,我收到“除非使用帐户密钥凭据,否则无法创建共享访问签名”。是否支持带有 MSI 的 SAS?
var container = blobClient.GetContainerReference(containerName);
var blockBlob = container.GetBlockBlobReference(snapname);
var sas = string.Concat(blockBlob.Uri.ToString(), blockBlob.GetSharedAccessSignature(sasConstraints));
这就是我创建 StorageCredentials 的方式:
tokenCallback = CreateMsiCallback();
var initToken = await tokenCallback(audience);
return new StorageCredentials(
new TokenCredential(initToken, async (state, token) =>
{
var accessToken = await _tokenCallback(audience);
return new NewTokenAndFrequency(accessToken, TimeSpan.FromMinutes(1));
}, null, TimeSpan.FromMinutes(1))
);
要创建令牌回调,我使用 HttpClient
public Func<string, Task<string>> CreateMsiCallback()
{
var handler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback =
(httpRequestMessage, cert, certChain, policyErrors) =>
{
if (policyErrors == SslPolicyErrors.None)
{
return true;
}
return 0 == string.Compare(cert.GetCertHashString(), FabricThumbprint, StringComparison.OrdinalIgnoreCase);
}
};
var client = new HttpClient(handler)
{
DefaultRequestHeaders =
{
{"secret", FabricAuthenticationCode }
}
};
return async (resource) =>
{
var requestUri = $"{FabricMsiEndpoint}?api-version={FabricApiVersion}&resource={HttpUtility.UrlEncode(resource)}";
var requestMessage = new HttpRequestMessage(HttpMethod.Get, requestUri);
var response = await client.SendAsync(requestMessage);
response.EnsureSuccessStatusCode();
var tokenResponseString = await response.Content.ReadAsStringAsync();
var tokenResponseObject =
JsonConvert.DeserializeObject<ManagedIdentityTokenResponse>(tokenResponseString);
return tokenResponseObject.AccessToken;
};
}
}
【问题讨论】:
-
既然使用了MSI,为什么不使用Azure ad auth来访问azure blob?
-
我们有一个框架可以连接到不同的环境,其中一些是基于 Service Fabric 的,一些不是,还有一些用于测试和本地机器开发。所以我们需要一个通用的 API。
标签: azure azure-blob-storage azure-managed-identity