Reputation: 5106
I've got a requirement to be able to copy a blob from a container in 1 storage account into a container in another storage account. Previously the source container had public access set to 'Container'. I was using the connection string to connect to the account and then get a reference to the blob.
I'm using StartCopyAsync(sourceBlob). This was originally working fine when the container had public access set to container. Now it throws a StorageException of 'The specified resource does not exist'. Is this a permissions thing? I would have expected an error message to say I didn't have permissions. I can see the resource is there in the container.
Assuming it is a permissions thing, is there a way to copy a blob from a container that has public access set to 'private'? The docs suggest it can be done by 'authorised request' but what how do you do that?
Update
I've tried Gaurav Mantri's suggestion but currently getting an error of "This request is not authorized to perform this operation". Here's my code:
private async Task<FileActionResult> CopyBlob(string blobName, string sourceBlobSasToken, string sourceBlobName, CloudBlockBlob targetBlob)
{
try
{
await targetBlob.StartCopyAsync(new Uri(sourceBlobSasToken));
var targetBlobRef = await _connectionFactory.GetContainerConnection(BlobContainerType.myTargetContainer).GetBlobReferenceFromServerAsync(targetBlob.Name);
while (targetBlobRef.CopyState.Status == CopyStatus.Pending)
{
await Task.Delay(500);
targetBlobRef = await _connectionFactory.GetContainerConnection(BlobContainerType.myTargetContainer).GetBlobReferenceFromServerAsync(targetBlob.Name);
}
if (targetBlobRef.CopyState.Status == CopyStatus.Success)
{
return new FileActionResult(blobName, true);
}
else
{
var errorMessage = $"{blobName} failed to copy from '{sourceBlobName}' to '{targetBlob}'. Status: {targetBlobRef.CopyState.Status}";
_logServiceApi.Trace(errorMessage);
return new FileActionResult(blobName, false, errorMessage);
}
}
catch (StorageException ex)
{
_logServiceApi.LogException(ex);
return new FileActionResult(blobName, false, ex.Message);
}
catch (AggregateException ex)
{
_logServiceApi.LogException(ex);
return new FileActionResult(blobName, false, ex.Message);
}
}
The 'sourceBlobSasToken' is retrieved by this bit of code and passed in:
public string GetFileStorageBlobSasUri(BlobContainerType blobContainer, string fileName, double tokenDuration, long? projectId = null)
{
var blob = GetBlockBlob(blobContainer, fileName, projectId);
var adHocPolicy = new SharedAccessBlobPolicy()
{
SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(tokenDuration),
Permissions = SharedAccessBlobPermissions.Read
};
var sasContainerToken = blob.GetSharedAccessSignature(adHocPolicy);
return blob.Uri + sasContainerToken;
}
Upvotes: 1
Views: 891
Reputation: 4544
It seems like you are not authorized to access the blobs of another container.
Well, in case to access the blobs, you can create an authentication request. You would require your account name and key to create an authorization header which gets passed along with the request to access the blobs. If this authorization header is not present in your request, the request will be rejected.
You can also visit https://learn.microsoft.com/en-us/azure/storage/blobs/anonymous-read-access-configure?tabs=portal to learn more on this.
Upvotes: 2
Reputation: 136146
It is indeed a permission issue. For copy blob operation to work, the source blob must be publicly accessible. From this link
:
When your container's ACL was public, the source blob was publicly accessible i.e. anybody could directly access the blob by its URL. However once you changed the container's ACL to private, the source blob is no longer publicly accessible.
To solve your problem, what you need to do is create a SAS URL for the source blob with at least Read
permission and use that SAS URL in your StartCopyAsync
method.
Upvotes: 2