GCPでCloud SDK(PHP)を使って署名付きURLを発行する

はじめに

GCPを使う機会が今後あるので、GCPのCloud Storageの署名付きURLをCloud SDKから発行することをやってみる。

環境

Windows 11 Professional
WSL2 Ubuntu24.04 LTS
Cloud SDK for PHP

準備

  • Google Cloud Platformのアカウント作成済み

Cloud Storageでバケットを作成する

1. GCPで「Cloud Storage」のサービスに移動する

create-bucket-01

2.バケット名の他オプションの設定を行い、「作成」を選択する

create-bucket-02 create-bucket-03

バケットのライフサイクルルールを設定する(1日経過したオブジェクトを削除する)

1. 作成したバケットの「ライフサイクル」から「ルールを追加」を選択する

setting-bucket-lifecycle-01

2. 「アクション」と「オブジェクト条件」を選択する

setting-bucket-lifecycle-02

「アクションを選択」: オブジェクトを削除する
「オブジェクト条件の選択」: 経過日数
を選択する。

3. ルールが追加されたことを確認する

setting-bucket-lifecycle-03

構築

ローカル環境を作る

環境の構築

例によって、Dockerで作る。
まずは、コマンドライン上で実行できれば良いので、適当に。

全体のファイル階層は以下のように作成。

├── compose.yml
├── docker
│   └── php
│       └── Dockerfile
└── src
    └── generateSignedURL.php
compose.yml
services:
  app:
    build:
      context: ./docker/php
    volumes:
     - ./src:/var/www/html
docker/php/Dockerfile
# https://hub.docker.com/_/php
FROM php:8.3-fpm-alpine

# install composer
COPY --from=composer:2.8.2 /usr/bin/composer /usr/bin/composer

# gcloudに必要なパッケージインストール
RUN apk add --no-cache \
    python3

# gcloud のインストール
WORKDIR /tmp
RUN curl -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-477.0.0-linux-x86_64.tar.gz
RUN tar -xf google-cloud-cli-477.0.0-linux-x86_64.tar.gz
RUN ./google-cloud-sdk/install.sh

WORKDIR /var/www/html
src/generateSignedURL.php
<?php
namespace Main;

echo "Hello,World!";

動作確認

docker compose up -d
docker compose exec app php generateSignedURL.php 
Hello World

と出力されればOK

Google Cloud SDKをcomposerで入れる

docker compose exec app composer require google/cloud-storage

src以下に、vendor, composer.json, composer.lockが出力される。

Google認証情報を取得する

https://cloud.google.com/docs/authentication/application-default-credentials?hl=ja に記載の通り、ローカル環境ではADCを利用する。

https://cloud.google.com/sdk/docs/install?hl=ja#linux に従って、gcloudのセットアップを完了させる。
Dockerfileでは、gcloudのインストールまで住んでいるので、initを実行する。

ADCを使う方法(ローカル)

1. Dockerコンテナに入る

docker compose exec app sh

2. gcloud initを実行する

/tmp/google-cloud-sdk/bin/gcloud init
Welcome! This command will take you through the configuration of gcloud.

Your current configuration has been set to: [default]

You can skip diagnostics next time by using the following flag:
  gcloud init --skip-diagnostics

Network diagnostic detects and fixes local network connection issues.
Checking network connection...done.                                                                                                                                                                                     
Reachability Check passed.
Network diagnostic passed (1/1 checks passed).

## ここで「Y」を選択する。
You must log in to continue. Would you like to log in (Y/n)?  Y

## URLが表示されるのでアクセス
https://XXXXXXXXXXXXXXXXXXXXXXXXXXXXX

## 表示したURLの認証コードを入力する
Once finished, enter the verification code provided in your browser: XXXXXXX

URLにアクセスするとこうなるので許可を選択。
gcloud-init-01

認証コードが表示されるので入力する。
gcloud-init-02

3. gcloud auth application-default loginを実行して、ログインをする

コンテナ内で以下を実行する。

gcloud auth application-default login

これを実行することで、/root/.config/gcloud/application_default_credentials.json に認証情報が保存される。

サービスアカウントキーを作成する

以下の手順で作成する。
https://cloud.google.com/iam/docs/creating-managing-service-account-keys?hl=ja

サービスアカウントキーの場合は上記で作成して、jsonファイルをダウンロードする。

コードを作成する

generateSignedURL.phpを下記のように作成する。

変数名設定値
$bucketNamepublish-signed-url-for-cloud-sdk-test
$filePathtestfile.txt
generateSignedURL.php
<?php
namespace Main;
require 'vendor/autoload.php';
use Google\Cloud\Storage\StorageClient;

putenv('GOOGLE_APPLICATION_CREDENTIALS=/var/www/html/credentials.json');

$bucketName = 'publish-signed-url-for-cloud-sdk-test';      // Google Cloud Storageのバケット名
$filePath   = 'testfile.txt'; // アップロードするローカルファイルのパス
$fileName = basename($filePath);
$id = uniqid();
$objectName = $id . '-infix-' . $fileName;     // Google Cloud Storageにアップロードする際のオブジェクト名

// ファイルアップロード
uploadFile($bucketName, $filePath, $objectName);

// 署名付きURLの生成
$signedUrl = generateSignedUrl($bucketName, $objectName);

echo "Signed URL: {$signedUrl}\n";

/**
 * ファイルアップロード
 * 
 * @param string $bucketName Google Cloud Storageのバケット名
 * @param string $filePath アップロードするローカルファイルのパス
 * @param string $objectName Google Cloud Storageにアップロードする際のオブジェクト名
 * 
 * @return void
 */
function uploadFile($bucketName, $filePath, $objectName)
{
    // StorageClientインスタンスの作成
    $storage = new StorageClient();

    // 指定したバケットを取得
    $bucket = $storage->bucket($bucketName);

    // ファイルをアップロード
    $object = $bucket->upload(
        fopen($filePath, 'r'),
        [
            'name' => $objectName
        ]
    );

    echo "File uploaded to {$bucketName}/{$objectName}\n";
}

/**
 * 署名付きURLの生成
 * 
 * @param string $bucketName Google Cloud Storageのバケット名 
 * @param string $objectName Google Cloud Storageにアップロードする際のオブジェクト名
 * 
 * @return string 署名付きURL
 * */
function generateSignedUrl($bucketName, $objectName)
{
    // StorageClientインスタンスの作成
    $storage = new StorageClient();

    // 指定したバケットを取得
    $bucket = $storage->bucket($bucketName);

    // 署名付きURLの期限(秒単位)
    $expires = new \DateTime('1 hour');

    // 署名付きURLを生成
    $url = $bucket->object($objectName)->signedUrl(
        $expires,
        [
            'version' => 'v4', // v4署名の使用
        ]
    );

    echo "Generated signed URL: {$url}\n";
    return $url;
}

src以下に、アップロード用のファイルを作成しておく。

testfile.txt
testtest

generateSignedURL.phpの動作確認

php -f generateSignedURL.php

結果↓

/var/www/html # php -f generateSignedURL.php 
File uploaded to publish-signed-url-for-cloud-sdk-test/672f53bce4030-infix-testfile.txt
Generated signed URL: https://storage.googleapis.com/publish-signed-url-for-cloud-sdk-test/672f53bce4030-infix-testfile.txt?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=637601981080-compute%40developer.gserviceaccount.com%2F20241109%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20241109T122117Z&X-Goog-Expires=3600&X-Goog-SignedHeaders=host&X-Goog-Signature=b268f9d6535bb9b0076e32d679382b3d929fccef95453513e621a0f2a405d41746ac759996a72bb926f0f9a622e0b70388ab6526c17d5ae42d9642e63f1ebecca4b7da32b9c9129ec23fd6a7388fa6660ad61f4fc1f6667da3ca48a692f9f17a02f0a674431f250b448cb56fc485909f447952a609c42a8e4f4aafeee6c0cc5d7059a3ba9d192fa8e4a6eeb20b07984569639498ae9874490bc3a867fdb4d6ab71e168cb21c30c7923f20c28c7d9ba5ae01ca546b35c44f300ec9fb7f05478f2fdfed520c59a9ec915a247b0712717b83cfdf643a20ec8f7f15c88e94b3b27abe8b4f24f9f7fc972e9ee458b7a714a1f0005207b7af9a5826f42306c91d73951
Signed URL: https://storage.googleapis.com/publish-signed-url-for-cloud-sdk-test/672f53bce4030-infix-testfile.txt?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=637601981080-compute%40developer.gserviceaccount.com%2F20241109%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20241109T122117Z&X-Goog-Expires=3600&X-Goog-SignedHeaders=host&X-Goog-Signature=b268f9d6535bb9b0076e32d679382b3d929fccef95453513e621a0f2a405d41746ac759996a72bb926f0f9a622e0b70388ab6526c17d5ae42d9642e63f1ebecca4b7da32b9c9129ec23fd6a7388fa6660ad61f4fc1f6667da3ca48a692f9f17a02f0a674431f250b448cb56fc485909f447952a609c42a8e4f4aafeee6c0cc5d7059a3ba9d192fa8e4a6eeb20b07984569639498ae9874490bc3a867fdb4d6ab71e168cb21c30c7923f20c28c7d9ba5ae01ca546b35c44f300ec9fb7f05478f2fdfed520c59a9ec915a247b0712717b83cfdf643a20ec8f7f15c88e94b3b27abe8b4f24f9f7fc972e9ee458b7a714a1f0005207b7af9a5826f42306c91d73951

Signed URLにアクセスするとダウンロードされればOK

バケットにはアップロードしたファイルが存在している。
confirm-signed-url-and-bucket-01

参考

おわりに

GCPでストレージにアップロードすることを実施した。
サービスアカウントキーとか権限周りよくわからないので勉強しておこう…。

Hugo で構築されています。
テーマ StackJimmy によって設計されています。