sr28
sr28

Reputation: 5106

How can you copy a blob in a container with public access set to 'Private'?

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

Answers (2)

Utkarsh Pal
Utkarsh Pal

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

Gaurav Mantri
Gaurav Mantri

Reputation: 136146

It is indeed a permission issue. For copy blob operation to work, the source blob must be publicly accessible. From this link:

enter image description here

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

Related Questions