Проблема синхронизации azcopy в Azure при синхронизации между контейнерами с использованием токена sas для многопользовательского приложения

#azure #azure-active-directory

#azure #azure-active-directory

Вопрос:

Я пытаюсь синхронизировать данные между контейнерами Azure в разных учетных записях с помощью мультитетантного приложения и инструмента azcopy.

Синхронизация происходит через «синхронизацию azcopy» и с использованием отдельных токенов SAS как для исходной учетной записи хранения, так и для целевой учетной записи хранения.

Я генерирую токены sas с коротким сроком службы, используя Java SDK, следуя методу ключа делегирования пользователя.

Вот сценарий:

В учетной записи Account1 (назначения) зарегистрировано приложение 1. т.Е. Учетная запись 1 является домашним арендатором для App1. У учетной записи Account1 есть StorageAccount1, а для настроенного контейнера Container1 App1 назначена роль «вкладчика данных большого двоичного объекта хранилища» в StorageAccount1

В учетной записи Account2 (источник) настроены StorageAccount2 и Container2. Для нас это источник данных. Здесь App1 добавляется как ServicePrincipal через:

 az ad sp create --id client-id-of-App1-in-Account1
 

В Account2 для этого SP мы также предоставили роль считывателя данных хранилища Blob как:

 az role assignment create 
   --assignee-object-id <object-id-for-this-sp> 
   --role 2a2b9908-6ea1-4ae2-8e65-a410df84e7d1 
   --scope /subscriptions/<subsid-account2>/resourceGroups/<resgrpname>/providers/Microsoft.Storage/storageAccounts/<storagename>
 

На этом настройка завершена.

Теперь, используя Java SDK, я сгенерировал ключ делегирования пользователя как для источника, так и для назначения. Фрагмент выглядит примерно так, как показано ниже.

 genSasToken(String storageAccountName, String containerName,
                             String tenantId,
                             String azureAppClientId,
                             String azureAppClientSecret,
                             boolean isDestinationAccount) {
    BlobContainerSasPermission blobContainerSasPermission =
        new BlobContainerSasPermission().setReadPermission(true).setListPermission(true);
    if (isDestinationAccount) {
      blobContainerSasPermission.setCreatePermission(true)
              .setAddPermission(true)
              .setWritePermission(true)
              .setExecutePermission(true);
    }
    BlobServiceSasSignatureValues builder =
        new BlobServiceSasSignatureValues(OffsetDateTime.now().plusHours(1), blobContainerSasPermission)
            .setProtocol(SasProtocol.HTTPS_ONLY);
    // Create a BlobServiceClient object which will be used to create a container client
    String endpoint = String.format(Locale.ROOT, "https://%s.blob.core.windows.net",
            storageAccountName);
    ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder()
                                                        .clientId(azureAppClientId)
                                                        .clientSecret(azureAppClientSecret)
                                                        .tenantId(tenantId)
                                                        .build();

    BlobServiceClient blobServiceClient =
        new BlobServiceClientBuilder().endpoint(endpoint).credential(clientSecretCredential).buildClient();
    BlobContainerClient blobContainerClient =
        blobServiceClient.getBlobContainerClient(containerName);
    // Get a user delegation key for the Blob service that's valid for one hour.
    // You can use the key to generate any number of shared access signatures over the lifetime of the key.
    OffsetDateTime keyStart = OffsetDateTime.now();
    OffsetDateTime keyExpiry = OffsetDateTime.now().plusHours(1);
    UserDelegationKey userDelegationKey = blobServiceClient.getUserDelegationKey(keyStart, keyExpiry);

    String sas = blobContainerClient.generateUserDelegationSas(builder, userDelegationKey);
    return sas;
  }
 

Вышеуказанный метод вызывается как для источника, так и для назначения и выдает нам токены SAS, сгенерированные программно.

Интересная вещь, которая происходит, заключается в следующем:

синхронизация azcopy https://storageaccount2/container2/?sas-token-for2 https://storageaccount1/container1/?sas-token-for1

вышеуказанные ошибки синхронизации отображаются как

 INFO: Authentication failed, it is either not correct, or expired, or does not have the correct permission -> github.com/Azure/azure-storage-blob-go/azblob.newStorageError, /Users/runner/go/pkg/mod/github.com/!azure/azure-storage-blob-go@v0.10.1-0.20201022074806-8d8fc11be726/azblob/zc_storage_error.go:42
===== RESPONSE ERROR (ServiceCode=AuthorizationFailure) =====
Description=This request is not authorized to perform this operation.
RequestId:xxx
Time:2021-01-27T10:26:34.9282634Z, Details:
   Code: AuthorizationFailure
   GET https://storageaccount1.blob.core.windows.net/container1/?comp=propertiesamp;restype=accountamp;se=2021-01-27t11:10:12zamp;sig=-REDACTED-amp;ske=2021-01-27t11:10:12zamp;skoid=xxxamp;sks=bamp;skt=2021-01-27t10:10:12zamp;sktid=xxxamp;skv=2020-02-10amp;sp=racwleamp;spr=httpsamp;sr=camp;sv=2020-02-10amp;timeout=901
   User-Agent: [AzCopy/10.8.0 Azure-Storage/0.10 (go1.13; darwin)]
   X-Ms-Client-Request-Id: [xxx]
   X-Ms-Version: [2019-12-12]
   --------------------------------------------------------------------------------
   RESPONSE Status: 403 This request is not authorized to perform this operation.
   Content-Length: [246]
   Content-Type: [application/xml]
   Date: [Wed, 27 Jan 2021 10:26:34 GMT]
   Server: [Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0]
   X-Ms-Client-Request-Id: [xxx]
   X-Ms-Error-Code: [AuthorizationFailure]
   X-Ms-Request-Id: [xxx]
   X-Ms-Version: [2019-12-12]
 

Но, когда я пытаюсь скопировать из источника на локальный хост, используя тот же токен sas 2, это работает.

синхронизация azcopy https://storageaccount2/container2/sas-token-for2 /tmp

и

когда я пытаюсь скопировать папку localhost в пункт назначения, используя тот же токен sas, он также работает.

синхронизация azcopy / tmp https://storageaccount1/container1/sas-token-for1

Таким образом, токены работают индивидуально, как указано выше.

Но синхронизация azcopy https://storageaccount2/container2/sas-token-for2 https://storageaccount1/container1/sas-token-for1

Сбой.

Любые указания, в чем может быть проблема?

Комментарии:

1.Кроме того, создание sas из azure portal для учетной записи хранилища назначения и ее использование в azcopy работает нормально. т.е. azcopy синхронизирует storageaccount2 / container2 / sas-token-for2 storageaccount1 / container1 / sas-token-generated-from-portal Это работает нормально.

2. Являются ли разрешения, используемые через портал и через код, идентичными для назначения? На самом деле, просто для проверки добавьте все разрешения в целевой SAS, а затем удаляйте по одному за раз. Для синхронизации требуются разрешения на удаление, которые я не вижу в коде, но для управления чем-либо еще мы начинаем с полных разрешений.

3. Да, разрешения в основном идентичны. Через код. Токен назначения sas: sv=2020-02-10amp;spr=httpsamp;se=2021-01-27T13:00:02Zamp;skoid=REDACTEDamp;sktid=REDACTEDamp;skt=2021-01-27T12:00:02Zamp;ske=2021-01-27T13:00:02Zamp;sks=bamp;skv=2020-02-10amp;sr=camp;sp=racwleamp;sig=REDACTED. через портал. Целевой токен sas: sv=2019-12-12amp;ss=bamp;srt=coamp;sp=rwlacamp;se=2021-01-27T18:28:32Zamp;st=2021-01-27T10:28:32Zamp;spr=httpsamp;sig=REDACTED.

Ответ №1:

Для синхронизации вам не требуется разрешение на выполнение (которое в любом случае все еще находится в предварительном просмотре). Просто удалите .setExecutePermission(true) , все должно быть хорошо. Фактически синхронизация должна работать только с разрешениями на чтение, запись и перечисление в пункте назначения.