【问题标题】:If src and dst are the same, what will happen when I call StartCopyAsync?如果 src 和 dst 相同,我调用 StartCopyAsync 会发生什么?
【发布时间】:2018-01-12 23:12:32
【问题描述】:

我们有一个新要求,即我们的所有数据都需要在静态和传输中进行加密以用于 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);
}

【问题讨论】:

  • 你试过了吗?也许你可以报告发生了什么。
  • 似乎工作正常,但它是异步的。所以它工作正常可能是一种侥幸。

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


【解决方案1】:

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

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

注意:我特指这个方法签名:StartCopyAsync(Uri, AccessCondition, AccessCondition, BlobRequestOptions, OperationContext, CancellationToken)

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

无论如何,我认为答案取决于您的加密,以及加密X 字节的结果是否为X 字节。由于您不自己执行加密,因此您无法知道幕后所做的事情。

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

但是,我不会指望太多思考相信的答案。我肯定想知道

然而,即使你可以做你想做的事,你不应该。如果您在所有这些过程中遇到故障会发生什么?

为了您的客户,您应该在一个 blob 中读取并写入另一个 blob。如果您绝对不可能更改当前的 blob 路径,那么您需要读取 blob,将其写入临时 blob,然后在成功时将临时 blob 复制到旧 blob 上,然后在成功时删除临时斑点。

其他一些细节:

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

  • 该方法并非旨在将任何内容复制到任何地方。它的意思是EncryptContainerContentsAsync

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

最后,当您使用Blob​Request​Options.Encryption​Policy 时,您需要为每个客户使用不同的密钥。您还需要一种频繁轮换密钥的方法,例如 90 到 120 天。我之所以这么说是因为我猜您正在根据某些合规性要求进行更改,并且他们迟早会想要这种级别的安全性。 会希望获得这种级别的安全性来保护自己免于因没有它而承担的责任。

您最终应该为每个客户获得一个密钥,该密钥存储在密钥保管库中并使用您的密钥进行保护,您还可以轮换该密钥。您可能还需要一个将您指向客户 blob 的表。通过这种方式,您可以随意更改客户的 blob 所在的位置以及使用的密钥。

【讨论】:

  • 很多非常好的反馈。感谢您抽出宝贵时间参与本次讨论。当我最初设计该方法时,其目的实际上是在两个 blob 存储帐户之间复制文件。然后,当我意识到我可以执行只需要重新上传 blob 内容的就地加密时,我做到了,所以我将 src 复制到 src。你提出的关于 EncryptionPolicy 的观点对我来说是新的,所以我想对这些属性做更多的研究。 (他们不会出现在我面前——也许那里有什么诡计)
  • @Pangamma 我为我所指的特定 StartCopyAsync 方法添加了指向 MSDN 文档的链接。
猜你喜欢
  • 2011-04-02
  • 1970-01-01
  • 2012-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多