如果src和dst相同,那么当我调用StartCopyAsync时会发生什么?

时间:2017-08-04 22:53:25

标签: c# azure azure-storage azure-storage-blobs

我们有一个新的要求,我们所有的数据都需要在静止时加密,并在传输中进行azure blob存储。我们刚刚启用了透明加密,因此新文件将被加密,但现有文件仍未加密。我们需要使用工具重新上传现有文件,以便加密。我的问题是,如果src和dst相同,当我调用StartCopyAsync时会发生什么?文件是否会被破坏?这是安全的操作吗?

private async Task CopyContainerContents(CloudBlobContainer src, CloudBlobContainer dst)
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    BlobResultSegment blobSegment =  await src.ListBlobsSegmentedAsync(
        prefix: "",
        useFlatBlobListing: true,
        blobListingDetails: BlobListingDetails.All,
        maxResults: null,
        currentToken: new BlobContinuationToken(),
        options: new BlobRequestOptions(), 
        operationContext: new OperationContext(),
        cancellationToken:new CancellationToken()
    );

    var blobs = blobSegment.Results.OfType<CloudBlob>().ToList();
    foreach (var blob in blobs)
    {
        CloudBlob srcBlob = (CloudBlob)blob;
        // regular file
        Console.WriteLine("Copying "+srcBlob.Name);
        CloudBlob dstBlob = dst.GetBlobReference(srcBlob.Name);
        await dstBlob.StartCopyAsync(srcBlob.Uri);
    }
    sw.Stop();
    Console.WriteLine("TOTAL TIME: "+sw.Elapsed.TotalSeconds);
}

1 个答案:

答案 0 :(得分:1)

我不得不说,我感到失望的是,当src等于this时,文档没有说明它是否会抛出异常,即dst。我会从一个简单的测试开始,因为你可能会得到一个例外,并立即得到答案。文档确实说,

  

启动异步操作以开始复制另一个块   团块

注意:我具体指的是此方法签名:StartCopyAsync(Uri, AccessCondition, AccessCondition, BlobRequestOptions, OperationContext, CancellationToken)

起初我认为你的for循环中有一些(缺失的)代码会在写入srcBlob之前加密dstBlob的内容。但现在我假设它没有显示Blob​Request​Options.Encryption​Policy

无论如何,我认为答案取决于您的加密,以及加密X字节的结果是否为X字节。由于您不自行执行加密,因此无法了解正在进行的操作。

相信当输入大小等于输出大小时你会没事的。如果在你的第一次读取中你说600字节,你肯定会写不超过600字节。即使你只写300字节而下一次读取是900字节,你也不会写入新的900字节,直到第一次读取的剩余300字节被写入。

但是,我不会在思考相信的情况下找到答案。我肯定想知道

但是,即使你可以做你想做的事,你也不应该。如果你在所有这些中间遇到失败会怎样?

为了您的客户,您应该阅读一个blob并写入另一个blob。如果您无法更改当前blob路径,则需要读取blob,将其写入临时blob,然后成功将temp blob复制到旧blob上,然后成功删除临时的blob。

其他几个尼特:

  • 应该调用以Async结尾的方法。这不是一个绝对的规则,但对于签名以async开头并返回Task的任何方法来说,这是一个非常好的策略。

  • 该方法无意将任何内容复制到任何地方。这意味着EncryptContainerContentsAsync

  • src故意也是dst,因此您不应该同时拥有这两个参数,否则将来有人会查看您的代码,并想知道它是否可以安全使用当src等于dst时。我认为你应该只使用一个container参数。然后返回新的blob或进行临时交换。

最后,当您使用Blob​Request​Options.Encryption​Policy时,您需要为每个客户使用不同的密钥。您还需要一种频繁旋转键的方法,例如90 - 120天。我这样说是因为我猜你正在改变这个以满足一些合规要求,迟早他们会想要这种安全级别。 希望这种安全级别能够保护自己免受不拥有它的责任。

您最终应该为每个存储在密钥保险库中的客户提供一个密钥,并使用您的密钥进行保护,您也可以将其旋转。您可能还需要一个表格指向客户的blob。通过这种方式,您可以根据需要更改客户blob的位置以及使用的密钥。