Облачное хранилище Google с сервисным аккаунтом — 403 Запрещено

Я реализую cron, автоматически получающий статистику установки моего приложения в Google Play Store. Итак, мне нужно загрузить файл из Google Cloud Storage и проанализировать его. Я сделал этот код:

// Set scopes to authorize full control of Cloud Storage

$scopes = array("https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/devstorage.full_control");


// Create new Google Client

$client = new Google_Client();


// Set path to ServiceAccount's credentials and link them to Google Client

putenv('GOOGLE_APPLICATION_CREDENTIALS=../../libs/GoogleAPICredentials/client_credentials_CPTS.json');
$client->useApplicationDefaultCredentials();
$client->setScopes($scopes);


// Create new Google Service Storage object to handle our repository

$service = new Google_Service_Storage($client);


// Get content of GCS repository

$request = $service->objects->listObjects("MY_BUCKET");


// Settings folders, files, buckets, names

$sourceBucket = "pubsite_prod_rev_BUCKET_IDENTIFIER";
$sourceObject = "installs_MY_APP_IDENTIFIER_" . $date->format("Ym") . "_overview.csv";
$localFile = "../files/temp/installs_MY_APP_IDENTIFIER_" . $date->format("Ym") . "_overview.csv";
$fullSrcObj = "stats/installs/" . $sourceObject;
$destinationBucket = "MY_BUCKET";
$destinationObject = $sourceObject;


// Create new Google Service Storage StorageObject object to handle a single object (file)

$postBody = new Google_Service_Storage_StorageObject($client);


try {
    // Copy stats app .CSV file from orignal repository (Google Play Store) to our bucket

    $response = $service->objects->copy($sourceBucket, $fullSrcObj, $destinationBucket, $destinationObject, $postBody);


    // Get the new object

    try {
        $object = $service->objects->get($destinationBucket, $destinationObject);
    }
    catch (Google_Service_Exception $e) {
        if ($e->getCode() == 404)
            echo ("[<b><span style=\"color:#DA4F34\">ERROR</span></b>] <b><span style=\"color:#DA4F34\">". $e->getMessage() ."</span></b><br><br>");
        throw $e;
    }


    // Download the new object on the MY_COMPAGNY server

    $uri = sprintf('https://storage.googleapis.com/%s/%s?alt=media&generation=%s', $destinationBucket, $destinationObject, $object->generation);
    $http = $client->authorize();
    $response = $http->get($uri);

    if ($response->getStatusCode() != 200) {
        echo ("[<b><span style=\"color:#DA4F34\">ERROR</span></b>] <b><span style=\"color:#DA4F34\">An unhandled error append !</span></b><br><br>");
        die();
    }


    // Save it into local file on MY_COMPAGNY server

    file_put_contents($localFile, $response->getBody());


    // Convert .CSV into php array

    $csv = array_map('str_getcsv', file($localFile));


    // Delete local file

    unlink($localFile);


    // Remove last line of CSV (Array) --> Empty - And remove first line of CSV (Array) --> Title line

    array_shift($csv);
    array_pop($csv);


    // Insert each line into MY_COMPAGNY Database

    $success = false;
    foreach ($csv as $row) {
        $success = insertAppInstallData(filter_var($row[0], FILTER_SANITIZE_STRING), (int)filter_var($row[$columnTotal], FILTER_SANITIZE_NUMBER_INT), (int)filter_var($row[$columnCurrent], FILTER_SANITIZE_NUMBER_INT))?true:  $success;
    }
    if (!$success)
        echo ("[<b><span style=\"color:#DA4F34\">ERROR</span></b>] <b><span style=\"color:#DA4F34\">DataBase insertion failure</span></b><br><br>");

}
catch (Google_Service_Exception $E) {
    echo ("[<b><span style=\"color:#DA4F34\">ERROR</span></b>] <b><span style=\"color:#DA4F34\">".$E->getMessage()." - ".$E->getTraceAsString()."</span></b><br><br>");
}

С учетной записью пользователя это работает хорошо, но с учетной записью службы у меня возникает ошибка 403, запрещенная при вызове $service->objects->copy().

{ 
   "error": 
   { 
        "errors": [ 
        { 
            "domain": "global", 
            "reason": "forbidden", 
            "message": "Forbidden" 
        }], 
        "code": 403, 
        "message": "Forbidden" 
    } 
}

Я дважды проверяю, есть ли хорошие учетные данные, авторизация IAM, клиент OAuth, ... и это все еще не работает.

Я не на Google Engine, я работаю на личном движке.

У кого-нибудь есть идея?

Доброго дня и с наступающим Новым годом!

Бен.


person RedLens834    schedule 06.01.2017    source источник


Ответы (1)


Причина, по которой вы получаете сообщение об ошибке 403, заключается в том, что вам не хватает делегирования на уровне домена и шага олицетворения пользователя. См. документацию здесь, чтобы понять, как получить доступ к данным пользователя с помощью службы Счета.

Процесс выглядит следующим образом:

$scopes = array("https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/devstorage.full_control");

$client = new Google_Client();
$client->useApplicationDefaultCredentials();    
$client->addScope($scopes); //Set scopes to client object
$client->setSubject("[email protected]"); // replace with the user account

Вы можете заставить его работать с учетной записью пользователя, потому что пользователь уже имеет доступ к ресурсу, но не к учетной записи службы, поэтому ошибка 403 запрещена. К сожалению, процесс делегирования на уровне домена и олицетворение пользователя работает только с учетными записями G Suite (ранее Google Apps). Другой альтернативой может быть совместное использование ресурсов с учетной записью службы, но это то, что я еще не исследовал и не уверен, что это возможно. Вы также можете обратиться к документации PHP Client Lib здесь< /а>. Я надеюсь, что эта информация будет полезной.

person Morfinismo    schedule 06.01.2017
comment
Спасибо за Ваш ответ. Но я получаю другую ошибку: "error_description": "Unauthorized client or scope in request.". Почему моя область действия недействительна, в то время как у моего xxxxxxxxxx@MY_PROJECT.iam.gserviceaccount.com есть все разрешения в консоли разработчика Google? И почему это не работает с моей служебной учетной записью? - person RedLens834; 06.01.2017
comment
Вы используете учетную запись G Suite или бесплатную учетную запись Gmail? - person Morfinismo; 06.01.2017
comment
Я использую бесплатную учетную запись gmail. Я плачу только за сервисы Google Cloud Storage - person RedLens834; 07.01.2017
comment
Можете ли вы попробовать поделиться ведром с учетной записью службы? Это может сработать. - person Morfinismo; 07.01.2017
comment
Я пробовал это с менеджером разрешений IAM, но он все еще не работает :( - person RedLens834; 12.01.2017