😺

Looker Studio から非公開の Cloud Storage PDF を開く

に公開

はじめに

こんにちは、クラウドエースのイリゴチです。
社内外のレポートやチェックシートなど、PDF を Google Cloud Storage に保存して運用するケースは多いと思います。
しかし、バケットを「非公開」のまま Looker Studio の表に「PDF を開く」リンクを出したい、というニーズも少なくありません。
本記事では、Cloud Run Functions(2nd gen) で「署名付き URL」を発行して即リダイレクトする小さな HTTP 関数を用意し、Looker Studio の 計算フィールド でその関数 URL を組み立ててクリック可能なリンクを表示する手順を紹介します。

目的

  • バケットは最後まで「非公開(Public なし)」
  • オブジェクト単位の GET のみ一時的に許可(署名付き URL)
  • Looker Studio の表の各行からワンクリックで PDF を表示

全体アーキテクチャ

  1. PDF は Google Cloud Storage (非公開) の特定バケットに保存
  2. Cloud Run Functions(2nd gen) の HTTP 関数に対して ?object=<オブジェクトのパス> を付けてアクセス
  3. 関数が V4 署名付き URL を生成し、302 リダイレクト
  4. ブラウザが署名付き URL へ遷移して PDF を表示
  5. Looker Studio 側では 計算フィールド で関数 URL を行ごとに組み立て、表に「PDF を開く」リンクを表示

ステップ 1:Google Cloud Storage に PDF を保管する

  • バケットは 非公開 のままにします。

  • PDF のオブジェクト名は、Looker Studio の行データから一意に導出できるパターンにします。

    • 例:<社員ID>_<連番>_<提出年月日>.pdf

日本語が含まれる場合は、URL エンコード される前提で運用します。

ステップ 2:Cloud Run Functions(2nd gen)の HTTP 関数を作成する

1. 関数

  1. Google Cloud Console の左メニューから 「Cloud Run」 を開きます。
  2. 右上の 「関数を作成」 をクリックします。
  3. サービスの名前リージョン を選択します。
  4. ランタイムは Python 3.12 を選択します。
  5. 認証で公開アクセスを許可するを選択します。
  6. コンテナ、ボリューム、ネットワーキング、セキュリティを開き、変数とシークレットを選択します。
  7. 以下 2 つの環境変数を追加します
    名前
    BUCKET_NAME PDFを保存したバケット名
    SIGNER_SERVICE_ACCOUNT Cloud Run のデフォルトサービスアカウント
  8. 作成を選択します。

💡 この設定により、Looker Studio から直接関数 URL にアクセスできるようになります。
実際の PDF ファイルは署名付き URL 経由でしかアクセスできないため、バケットは非公開のままで安全です。

2. ソース

ディレクトリ構成(Python 3.12)

.
├── main.py
└── requirements.txt

requirements.txt

functions-framework==3.*
google-cloud-storage==2.*
flask==3.*
google-auth==2.*

main.py

関数のエントリポイントにはget_signed_urlと入力してください。

import os
import functions_framework
from google.cloud import storage
from datetime import timedelta
from flask import Request, redirect

import google.auth
import google.auth.transport.requests

BUCKET_NAME = os.environ.get("BUCKET_NAME")  
SERVICE_ACCOUNT_EMAIL = os.environ.get("SIGNER_SERVICE_ACCOUNT")  

@functions_framework.http
def get_signed_url(request: Request):
    """
    非公開バケットのオブジェクトに対し、V4 署名付き URL を生成して 302 リダイレクトします。
    クエリ: ?object=<オブジェクト名(パス)>
    """
    object_name = request.args.get("object")
    if not BUCKET_NAME:
        return ("Server misconfiguration: BUCKET_NAME is not set.", 500)
    if not SERVICE_ACCOUNT_EMAIL:
        return ("Server misconfiguration: SIGNER_SERVICE_ACCOUNT is not set.", 500)
    if not object_name:
        return ("Error: 'object' parameter is required.", 400)

    # アクセストークンを取得(鍵レス署名)
    credentials, _ = google.auth.default()
    credentials.refresh(google.auth.transport.requests.Request())

    try:
        storage_client = storage.Client()
        bucket = storage_client.bucket(BUCKET_NAME)
        blob = bucket.blob(object_name)

        signed_url = blob.generate_signed_url(
            version="v4",
            expiration=timedelta(minutes=15),
            method="GET",
            service_account_email=SERVICE_ACCOUNT_EMAIL,
            access_token=credentials.token,
        )
        # 署名付き URL へリダイレクト
        return redirect(signed_url, code=302)

    except Exception as e:
        # 例外は Cloud Logging に出力されます
        print(f"signing error: {e}")
        return ("Internal Server Error: Could not generate signed URL.", 500)

3. 権限

署名に使用するサービスアカウントに、以下の権限をIAM と管理から付与します。

  • roles/iam.serviceAccountTokenCreator
  • roles/storage.objectViewer

ステップ 3:Looker Studio の計算フィールドでリンクを作成する

  1. データソース(BigQuery 等)に、PDF の オブジェクト名 を組み立てられる列(または組み合わせ)を用意します。
  2. チャート(表)の 計算フィールド を新規作成し、次のように関数 URL を合成します。

計算フィールド例

HYPERLINK(
  CONCAT(
    "https://<関数のURL>/",
    "?object=<フォルダ名>/",
      CONCAT(
        TRIM(<Looker Studio のフィールド名>), "_",
        TRIM(<Looker Studio のフィールド名>), "_",
        TRIM(<Looker Studio のフィールド名>),
        ".pdf"
      )
    ),
  "PDF を開く"
)
  • 関数の URL は Cloud Run Functions の関数画面上部にあります。

  • フォルダ名は PDF を格納しているバケット内のフォルダ名です。フォルダがない場合は "?object=",と記入し、オブジェクト名の指定は不要です。
  • CONCAT 内は実際の PDF ファイル名の形式に該当する Looker Studio のフィールドを記入します。
  • 出力は「PDF を開く」という クリック可能なリンク になります。
  • リンクをクリックすると関数が呼び出され、署名付き URL へリダイレクトされて PDF が表示されます。

オブジェクト名に日本語が含まれる場合、URL エンコードが必要です。
Looker Studio 上では変換できないため、JSON.stringify()を使用して、事前にエンコード済みの文字列を取得し、その変換結果を計算フィールドに記入してください。
以下はコード例です。

console.log(encodeURIComponent("オブジェクト名"))

さいごに

  • バケットを非公開のまま、Cloud Run Functions(2nd gen)V4 署名付き URL を発行・リダイレクトすることで、Looker Studio から安全に PDF を開けます。
  • Looker Studio 側は 計算フィールドの HYPERLINKURL エンコード だけで実現でき、既存の表にシンプルに組み込めます。
  • IMAGE 関数と組み合わせることで画像のサムネイル表示も実現可能です。

Discussion