从 minikube 执行时来自 Javascript 库 (@azure/storage-blob) 的 beginCopyFromURL API 的授权错误
Authorization Error from beginCopyFromURL API from Javascript library (@azure/storage-blob) when executed from minikube
我在 Azure 中注册了应用程序,它具有存储帐户参与者角色。我正在尝试使用 SAS 令牌将内容从一个帐户复制到同一订阅中的另一个帐户。以下是用于测试目的的代码片段。 此代码在独立节点 js 中运行良好,但在部署在 minikube pod 中时失败,授权错误代码为 403。任何 suggestions/thoughts 将不胜感激。
- 我已经验证了签名的开始和结束日期。
- 权限范围更广,但它们似乎是正确的。
- 用于测试保质期 24 小时。
- 如果我复制从失败代码生成的 sas url,我可以使用 azcopy 命令行从我的主机下载文件。看起来代码只有在从 minikube pod 执行时才会失败。
const { ClientSecretCredential } = require("@azure/identity");
const { BlobServiceClient, UserDelegationKey, ContainerSASPermissions, generateBlobSASQueryParameters } = require("@azure/storage-blob");
module.exports = function () {
/*
This function will receive an input that conforms to the schema specified in
activity.json. The output is a callback function that follows node's error first
convention. The first parameter is either null or an Error object. The second parameter
of the output callback should be a JSON object that conforms to the schema specified
in activity.json
*/
this.execute = async function (input, output) {
try {
if (input.connection) {
const containerName = input.sourcecontainer.trim()
const credential = new ClientSecretCredential(input.connection.tenantId, input.connection.clientid, input.connection.clientsecret);
const { BlobServiceClient } = require("@azure/storage-blob");
// Enter your storage account name
const account = input.sourceaccount.trim();
const accounturl = 'https://'.concat(account).concat('.blob.core.windows.net')
const blobServiceClient = new BlobServiceClient(
accounturl,
credential);
const keyStart = new Date()
const keyExpiry = new Date(new Date().valueOf() + 86400 * 1000)
const userDelegationKey = await blobServiceClient.getUserDelegationKey(keyStart, keyExpiry);
console.log(userDelegationKey)
const containerSAS = generateBlobSASQueryParameters({
containerName,
permissions: ContainerSASPermissions.parse("racwdl"),
startsOn: new Date(),
expiresOn: new Date(new Date().valueOf() + 86400 * 1000),
},
userDelegationKey, account).toString();
const target = '/' + containerName + '/' + input.sourcefolder.trim() + '/' + input.sourcefilename.trim()
const sastoken = accounturl + target + '?' + containerSAS
console.log(sastoken)
let outputData = {
"sourcesas": sastoken
}
//Testing second action execution from same action for testing purpose.
const containerName2 = 'targettestcontainer'
const credential2 = new ClientSecretCredential(input.connection.tenantId, input.connection.clientid, input.connection.clientsecret);
// Enter your storage account name
const blobServiceClient2 = new BlobServiceClient(
accounturl,
credential2);
const destContainer = blobServiceClient2.getContainerClient(containerName2);
const destBlob = destContainer.getBlobClient('testfolder01' + '/' + 'test-code.pdf');
const copyPoller = await destBlob.beginCopyFromURL(outputData.sourcesas);
const result = await copyPoller.pollUntilDone();
return output(null, outputData)
}
} catch (e) {
console.log(e)
return output(e, null)
}
}
}
谢谢 EmmaZhu-MSFT for providing the solution. Simmilar issue also raise in github 将此作为答案发布以帮助其他社区成员。
From service side log, seems there's time skew between Azure Storage
Service and the client, the start time used in source SAS token was
later than server time.
We'd suggest not using start time in SAS token to avoid this kind of
failure caused by time skew.
我在 Azure 中注册了应用程序,它具有存储帐户参与者角色。我正在尝试使用 SAS 令牌将内容从一个帐户复制到同一订阅中的另一个帐户。以下是用于测试目的的代码片段。 此代码在独立节点 js 中运行良好,但在部署在 minikube pod 中时失败,授权错误代码为 403。任何 suggestions/thoughts 将不胜感激。
- 我已经验证了签名的开始和结束日期。
- 权限范围更广,但它们似乎是正确的。
- 用于测试保质期 24 小时。
- 如果我复制从失败代码生成的 sas url,我可以使用 azcopy 命令行从我的主机下载文件。看起来代码只有在从 minikube pod 执行时才会失败。
const { ClientSecretCredential } = require("@azure/identity");
const { BlobServiceClient, UserDelegationKey, ContainerSASPermissions, generateBlobSASQueryParameters } = require("@azure/storage-blob");
module.exports = function () {
/*
This function will receive an input that conforms to the schema specified in
activity.json. The output is a callback function that follows node's error first
convention. The first parameter is either null or an Error object. The second parameter
of the output callback should be a JSON object that conforms to the schema specified
in activity.json
*/
this.execute = async function (input, output) {
try {
if (input.connection) {
const containerName = input.sourcecontainer.trim()
const credential = new ClientSecretCredential(input.connection.tenantId, input.connection.clientid, input.connection.clientsecret);
const { BlobServiceClient } = require("@azure/storage-blob");
// Enter your storage account name
const account = input.sourceaccount.trim();
const accounturl = 'https://'.concat(account).concat('.blob.core.windows.net')
const blobServiceClient = new BlobServiceClient(
accounturl,
credential);
const keyStart = new Date()
const keyExpiry = new Date(new Date().valueOf() + 86400 * 1000)
const userDelegationKey = await blobServiceClient.getUserDelegationKey(keyStart, keyExpiry);
console.log(userDelegationKey)
const containerSAS = generateBlobSASQueryParameters({
containerName,
permissions: ContainerSASPermissions.parse("racwdl"),
startsOn: new Date(),
expiresOn: new Date(new Date().valueOf() + 86400 * 1000),
},
userDelegationKey, account).toString();
const target = '/' + containerName + '/' + input.sourcefolder.trim() + '/' + input.sourcefilename.trim()
const sastoken = accounturl + target + '?' + containerSAS
console.log(sastoken)
let outputData = {
"sourcesas": sastoken
}
//Testing second action execution from same action for testing purpose.
const containerName2 = 'targettestcontainer'
const credential2 = new ClientSecretCredential(input.connection.tenantId, input.connection.clientid, input.connection.clientsecret);
// Enter your storage account name
const blobServiceClient2 = new BlobServiceClient(
accounturl,
credential2);
const destContainer = blobServiceClient2.getContainerClient(containerName2);
const destBlob = destContainer.getBlobClient('testfolder01' + '/' + 'test-code.pdf');
const copyPoller = await destBlob.beginCopyFromURL(outputData.sourcesas);
const result = await copyPoller.pollUntilDone();
return output(null, outputData)
}
} catch (e) {
console.log(e)
return output(e, null)
}
}
}
谢谢 EmmaZhu-MSFT for providing the solution. Simmilar issue also raise in github 将此作为答案发布以帮助其他社区成员。
From service side log, seems there's time skew between Azure Storage Service and the client, the start time used in source SAS token was later than server time.
We'd suggest not using start time in SAS token to avoid this kind of failure caused by time skew.