使用rbac Service Principal进行身份验证导致403受众验证失败。观众不一致
我试图让应用程序访问blob存储容器,但具有最低要求的权限(读/写)
使用azure cli我已经完成了以下步骤来尝试:
az group create -l ${LOCATION} -n ${RESOURCE_GROUP_NAME}
az role definition create --role-definition rw-blob-role.json
rw-blob-role.json:
{
"assignableScopes": [
"/subscriptions/{{SUBSCRIPTION_ID}}"
],
"description": "Custom role to allow for read and write access to Azure Storage blob containers and data",
"name": "{{APP_RW_ROLE_NAME}}",
"permissions": [
{
"actions": [
"Microsoft.Storage/storageAccounts/blobServices/containers/read",
"Microsoft.Storage/storageAccounts/blobServices/containers/write"
],
"dataActions": [
"Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read",
"Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write"
],
"notActions": [],
"notDataActions": []
}
],
"type": "Microsoft.Authorization/roleDefinitions"
}
az ad sp create-for-rbac --name ${AZ_SERVICE_PRINCIPAL_NAME} --password ${APP_CLIENT_SECRET}
az role assignment delete --assignee ${AZ_SERVICE_PRINCIPAL_NAME} --role Contributor
az role assignment create --assignee ${AZ_SERVICE_PRINCIPAL_NAME} --role ${APP_RW_ROLE_NAME}
az storage account create --name ${STORAGE_ACCOUNT_NAME} --resource-group ${RESOURCE_GROUP_NAME} --location ${LOCATION} --kind BlobStorage --sku ${STORAGE_ACCOUNT_SKU} --access-tier ${STORAGE_ACCOUNT_ACCESS_TIER}
az storage container create --name ${BLOB_STORAGE_CONTAINER} --account-name ${STORAGE_ACCOUNT_NAME} --public-access off
从这里我保存我的应用程序使用以下属性: - TENANT_ID =“$(az account show --output tsv --query tenantId)” - CLIENT_ID =“$(az ad sp list --spn $ {AZ_SERVICE_PRINCIPAL_NAME} --output tsv --query [0] .appId)” - 客户机密:$ {APP_CLIENT_SECRET} - 资源:$ {AZ_SERVICE_PRINCIPAL_NAME} - 存储帐户名称:$ {STORAGE_ACCOUNT_NAME} - 容器名称:$ {BLOB_STORAGE_CONTAINER}
使用com.microsoft.azure:adal4j我获取一个令牌:
public AuthenticationResult getToken() {
ExecutorService service = Executors.newFixedThreadPool(1);
ClientCredential credential = new ClientCredential(CLIENT_ID, APP_CLIENT_SECRET);
String authorityTenantUrl = String.format(https://login.microsoftonline.com/%s/oauth2/token, TENANT_ID);
AuthenticationContext context;
AuthenticationResult result;
try {
context = new AuthenticationContext(authorityTenantUrl, true, service);
Future<AuthenticationResult> future = context.acquireToken(AZ_SERVICE_PRINCIPAL_NAME, credential, null);
result = future.get();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
service.shutdown();
}
if (result == null) {
throw new RuntimeException("authentication result was null");
}
return result;
}
使用AuthenticationResult和com.microsoft.azure:azure-storage-blob中的accessToken尝试获取blob:
TokenCredentials credential = new TokenCredentials(accessToken);
HttpPipeline pipeline = StorageURL.createPipeline(credentials, new PipelineOptions());
ServiceURL serviceURL = new ServiceURL("https://STORAGE_ACCOUNT_NAME.blob.core.windows.net", pipeline);
ContainerURL containerURL = serviceURL.createContainerURL(BLOB_STORAGE_CONTAINER);
BlockBlobURL blobURL = containerURL.createBlockBlobURL(identifier);
ByteBuffer byteBuffer = FlowableUtil.collectBytesInBuffer(blobURL.download().blockingGet().body(new ReliableDownloadOptions())).blockingGet();
这会导致StorageException:
<Error>
<Code>AuthenticationFailed</Code>
<Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.</Message>
<AuthenticationErrorDetail>Audience validation failed. Audience did not match.</AuthenticationErrorDetail>
</Error>
我很确定问题是在acquireToken()上传递给adal4j的AZ_SERVICE_PRINCIPAL_NAME但我不知道正确的值是什么。我已尝试在租户AD和服务主体上使用CLIENT_ID和其他属性。
您应该使用https://storage.azure.com/
作为Resource的值。