Cloud Run でのエンドユーザー認証のチュートリアル

このチュートリアルでは、Cloud Run を使用して、ログイン ユーザーと PostgreSQL に保存されているデータに対するアクセスを制限するウェブ アプリケーションを作成します。Identity Platform を統合してエンドユーザー認証を処理します。これにより、Cloud SQL データベースにクエリを実行するサービスの認証で使用するユーザー ID トークンが提供されます。このサービスでは、一般公開のクライアントを使用して外部ユーザーが投票 UI にログインし、投票を行います。

説明をわかりやすくするため、このチュートリアルでは Google をプロバイダとして使用しています。ユーザーは Google アカウントでログインする必要があります。ただし、ユーザーのログインに他のプロバイダや認証方法を使用することもできます。

このサービスでは、セキュリティ リスクを最小限に抑えるため、Secret Manager を使用して Cloud SQL インスタンスへの接続で使用されるセンシティブ データを保護し、最小権限のサービス ID を使用します。

このサンプルでエンドユーザーが認証されるときに、次の処理が行われます。

  1. クライアントは Identity Platform に基づいてユーザーの署名付き ID トークンをリクエストします。
  2. 署名付き ID トークンがリクエストと一緒にサーバーに送信されます。
  3. サーバーは、その署名付き ID トークンを使用してユーザー ID を検証し、Cloud SQL PostgreSQL データベースへのアクセスを許可します。

このチュートリアルでは、次の認証方法について説明しません。

  • IAM 認証。IAM ロールを使用して自動的に ID を検証します。これは、個々の ID ではなくサービス間の認証を行う際に推奨される方法です。サービス間の認証の詳細については、Cloud Run サービスのセキュリティ保護のチュートリアルをご覧ください。現在のところ、IAM ベースの認証と ID トークンを組み合わせることはできません。

目標

  • 次のことを行うサービスを作成、ビルドし、Cloud Run にデプロイします。

    • Identity Platform を使用して Cloud Run サービスにアクセスするエンドユーザーを認証する。

    • Secret Manager を使用してセンシティブ データを処理し、Cloud Run サービスを PostgreSQL データベースに接続する。

  • 最小権限のサービス ID を作成して、Google Cloud リソースへのアクセスを最小限にする。

料金

このチュートリアルでは、Google Cloud の課金対象となる以下のコンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを出すことができます。

このプロジェクトは、無料トライアル クレジットの範囲内で完了できるはずです。

新しい Cloud Platform ユーザーは無料トライアルをご利用いただけます。

始める前に

  1. Google Cloud アカウントにログインします。Google Cloud を初めて使用する場合は、アカウントを作成して、実際のシナリオでの Google プロダクトのパフォーマンスを評価してください。新規のお客様には、ワークロードの実行、テスト、デプロイができる無料クレジット $300 分を差し上げます。
  2. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  3. Cloud プロジェクトに対して課金が有効になっていることを確認します。プロジェクトに対して課金が有効になっていることを確認する方法を学習する

  4. Cloud Run, Secret Manager, Cloud SQL, Container Registry, and Cloud Build API を有効にします。

    API を有効にする

  5. Cloud SDK をインストールして初期化します。

gcloud のデフォルトを設定する

Cloud Run サービスを gcloud のデフォルトに構成するには:

  1. デフォルト プロジェクトを設定します。

    gcloud config set project PROJECT_ID

    PROJECT_ID は、このチュートリアルで作成したプロジェクトの名前に置き換えます。

  2. 選択したリージョン向けに gcloud を構成します。

    gcloud config set run/region REGION

    REGION は、任意のサポートされている Cloud Run のリージョンに置き換えます。

Cloud Run のロケーション

Cloud Run はリージョナルです。つまり、Cloud Run サービスを実行するインフラストラクチャは特定のリージョンに配置され、そのリージョン内のすべてのゾーンで冗長的に利用できるように Google によって管理されます。

レイテンシ、可用性、耐久性の要件を満たしていることが、Cloud Run サービスを実行するリージョンを選択する際の主な判断材料になります。一般的には、ユーザーに最も近いリージョンを選択できますが、Cloud Run サービスで使用されている他の Google Cloud サービスのロケーションも考慮する必要があります。使用する Google Cloud プロダクトが複数のロケーションにまたがっていると、サービスの料金だけでなくレイテンシにも影響します。

Cloud Run は、次のリージョンで利用できます。

ティア 1 料金を適用

  • asia-east1(台湾)
  • asia-northeast1(東京)
  • asia-northeast2(大阪)
  • europe-north1(フィンランド) リーフアイコン 低 CO2
  • europe-west1(ベルギー)
  • europe-west4(オランダ)
  • us-central1(アイオワ) リーフアイコン 低 CO2
  • us-east1(サウスカロライナ)
  • us-east4(北バージニア)
  • us-west1(オレゴン) リーフアイコン 低 CO2

ティア 2 料金を適用

  • asia-east2(香港)
  • asia-northeast3(ソウル、韓国)
  • asia-southeast1(シンガポール)
  • asia-southeast2 (ジャカルタ)
  • asia-south1(ムンバイ、インド)
  • asia-south2(デリー、インド)
  • australia-southeast1(シドニー)
  • australia-southeast2(メルボルン)
  • europe-central2(ワルシャワ、ポーランド)
  • europe-west2(ロンドン、イギリス)
  • europe-west3(フランクフルト、ドイツ)
  • europe-west6(チューリッヒ、スイス) リーフアイコン 低 CO2
  • northamerica-northeast1(モントリオール) リーフアイコン 低 CO2
  • southamerica-east1(サンパウロ、ブラジル) リーフアイコン 低 CO2
  • us-west2(ロサンゼルス)
  • us-west3(ラスベガス)
  • us-west4(ソルトレイクシティ)

Cloud Run サービスをすでに作成している場合は、Cloud Console の Cloud Run ダッシュボードにリージョンを表示できます。

サンプルコードを取得する

使用するサンプルコードを取得するには:

  1. ローカルマシンにサンプルアプリのリポジトリのクローンを作成します。

    Node.js

    git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git

    または、zip 形式のサンプルをダウンロードし、ファイルを抽出してもかまいません。

    Python

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git

    または、zip 形式のサンプルをダウンロードし、ファイルを抽出してもかまいません。

    Java

    git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git

    または、zip 形式のサンプルをダウンロードし、ファイルを抽出してもかまいません。

  2. Cloud Run のサンプルコードが含まれているディレクトリに移動します。

    Node.js

    cd nodejs-docs-samples/run/idp-sql/

    Python

    cd python-docs-samples/run/idp-sql/

    Java

    cd java-docs-samples/run/idp-sql/

アーキテクチャを可視化する

アーキテクチャ図
この図は、IdP によって提供された Google ログイン ポップアップを使用してユーザーがログインし、その後、ユーザー ID を使用して Cloud Run にリダイレクトされる流れを表しています。
  1. ユーザーがサービスに対して最初のリクエストを行います。

  2. Cloud Run サービスが、ユーザーにユーザー ログイン フォームを表示します。

  3. ユーザーが、Identity Platform を使用する Google ログイン ポップアップ ウィンドウからログインします。

  4. 認証フローが、ユーザーの ID とともにユーザーを Cloud Run サービスに戻します。

  5. ユーザーが投票を行うと、クライアントは ID トークンを作成し、サーバー リクエストに追加します。サーバーが ID トークンを確認し、Cloud SQL への書き込みアクセス権を付与します。

コードの説明

このサンプルは、以下のようにクライアントとサーバーとして実装されます。

Identity Platform との統合: クライアント側のコード

このサンプルでは、Firebase SDK を使用して Identity Platform と統合し、ユーザーのログインと管理を行います。Identity Platform に接続するため、クライアント側の JavaScript はプロジェクトの認証情報への参照を構成オブジェクトとして保持し、必要な Firebase JavaScript SDK をインポートします。

const config = {
  apiKey: 'API_KEY',
  authDomain: 'PROJECT_ID.firebaseapp.com',
};
<!-- Firebase App (the core Firebase SDK) is always required and must be listed first-->
<script src="https://www.gstatic.com/firebasejs/7.18/firebase-app.js"></script>
<!-- Add Firebase Auth service-->
<script src="https://www.gstatic.com/firebasejs/7.18/firebase-auth.js"></script>

Firebase JavaScript SDK は、ポップアップ ウィンドウを開いて、Google アカウントでログインするようユーザーに促します。ユーザーがログインすると、サービスにリダイレクトします。

function signIn() {
  const provider = new firebase.auth.GoogleAuthProvider();
  provider.addScope('https://www.googleapis.com/auth/userinfo.email');
  firebase
    .auth()
    .signInWithPopup(provider)
    .then(result => {
      // Returns the signed in user along with the provider's credential
      console.log(`${result.user.displayName} logged in.`);
      window.alert(`Welcome ${result.user.displayName}!`);
    })
    .catch(err => {
      console.log(`Error during sign in: ${err.message}`);
      window.alert('Sign in failed. Retry or check your browser logs.');
    });
}

ユーザーがログインに成功すると、Firebase メソッドがユーザーの識別に使用する ID トークンを作成し、ユーザーにアクセスを許可します。クライアントが、ID トークンを含む Authorization ヘッダーを追加して、サーバーと通信します。

async function vote(team) {
  if (firebase.auth().currentUser) {
    // Retrieve JWT to identify the user to the Identity Platform service.
    // Returns the current token if it has not expired. Otherwise, this will
    // refresh the token and return a new one.
    try {
      const token = await firebase.auth().currentUser.getIdToken();
      const response = await fetch('/', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
          Authorization: `Bearer ${token}`,
        },
        body: 'team=' + team, // send application data (vote)
      });
      if (response.ok) {
        const text = await response.text();
        window.alert(text);
        window.location.reload();
      }
    } catch (err) {
      console.log(`Error when submitting vote: ${err}`);
      window.alert('Something went wrong... Please try again!');
    }
  } else {
    window.alert('User not signed in.');
  }
}

Identity Platform との統合: サーバー側のコード

サーバーは、Firebase Admin SDK を使用して Identity Platform を統合し、クライアントから送信されたユーザー ID トークンからユーザーの ID を確認します。提供された ID トークンが正しい形式で、期限切れではなく、適切に署名されている場合、このメソッドは、デコードされた ID トークンを返します。これは、ユーザーの Identity Platform uid を抽出する際に必要になります。

Node.js

const firebase = require('firebase-admin');
// Initialize Firebase Admin SDK
firebase.initializeApp();

// Extract and verify Id Token from header
const authenticateJWT = (req, res, next) => {
  const authHeader = req.headers.authorization;
  if (authHeader) {
    const token = authHeader.split(' ')[1];
    // If the provided ID token has the correct format, is not expired, and is
    // properly signed, the method returns the decoded ID token
    firebase
      .auth()
      .verifyIdToken(token)
      .then(decodedToken => {
        const uid = decodedToken.uid;
        req.uid = uid;
        next();
      })
      .catch(err => {
        req.logger.error(`Error with authentication: ${err}`);
        return res.sendStatus(403);
      });
  } else {
    return res.sendStatus(401);
  }
};

Python

def jwt_authenticated(func: Callable[..., int]) -> Callable[..., int]:
    @wraps(func)
    def decorated_function(*args: Any, **kwargs: Any) -> Any:
        header = request.headers.get("Authorization", None)
        if header:
            token = header.split(" ")[1]
            try:
                decoded_token = firebase_admin.auth.verify_id_token(token)
            except Exception as e:
                logger.exception(e)
                return Response(status=403, response=f"Error with authentication: {e}")
        else:
            return Response(status=401)

        request.uid = decoded_token["uid"]
        return func(*args, **kwargs)

    return decorated_function

Java

/** Extract and verify Id Token from header */
private String authenticateJwt(Map<String, String> headers) {
  String authHeader =
      (headers.get("authorization") != null)
          ? headers.get("authorization")
          : headers.get("Authorization");
  if (authHeader != null) {
    String idToken = authHeader.split(" ")[1];
    // If the provided ID token has the correct format, is not expired, and is
    // properly signed, the method returns the decoded ID token
    try {
      FirebaseToken decodedToken = FirebaseAuth.getInstance().verifyIdToken(idToken);
      String uid = decodedToken.getUid();
      return uid;
    } catch (FirebaseAuthException e) {
      logger.error("Error with authentication: " + e.toString());
      throw new ResponseStatusException(HttpStatus.FORBIDDEN, "", e);
    }
  } else {
    logger.error("Error no authorization header");
    throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
  }
}

Cloud SQL への接続

サービスは、/cloudsql/CLOUD_SQL_CONNECTION_NAME の形式を使用して、Cloud SQL インスタンスの Unix ドメイン ソケットに接続します。

Node.js

/**
 * Connect to the Cloud SQL instance through UNIX Sockets
 *
 * @param {object} credConfig The Cloud SQL connection configuration from Secret Manager
 * @returns {object} Knex's PostgreSQL client
 */
const connectWithUnixSockets = async credConfig => {
  const dbSocketPath = process.env.DB_SOCKET_PATH || '/cloudsql';
  // Establish a connection to the database
  return Knex({
    client: 'pg',
    connection: {
      user: credConfig.DB_USER, // e.g. 'my-user'
      password: credConfig.DB_PASSWORD, // e.g. 'my-user-password'
      database: credConfig.DB_NAME, // e.g. 'my-database'
      host: `${dbSocketPath}/${credConfig.CLOUD_SQL_CONNECTION_NAME}`,
    },
    ...config,
  });
};

Python

def init_unix_connection_engine(
    db_config: Dict[str, str]
) -> sqlalchemy.engine.base.Engine:
    creds = credentials.get_cred_config()
    db_user = creds["DB_USER"]
    db_pass = creds["DB_PASSWORD"]
    db_name = creds["DB_NAME"]
    db_socket_dir = creds.get("DB_SOCKET_DIR", "/cloudsql")
    cloud_sql_connection_name = creds["CLOUD_SQL_CONNECTION_NAME"]

    pool = sqlalchemy.create_engine(
        # Equivalent URL:
        # postgres+pg8000://<db_user>:<db_pass>@/<db_name>
        #                         ?unix_sock=<socket_path>/<cloud_sql_instance_name>/.s.PGSQL.5432
        sqlalchemy.engine.url.URL.create(
            drivername="postgresql+pg8000",
            username=db_user,  # e.g. "my-database-user"
            password=db_pass,  # e.g. "my-database-password"
            database=db_name,  # e.g. "my-database-name"
            query={
                "unix_sock": "{}/{}/.s.PGSQL.5432".format(
                    db_socket_dir, cloud_sql_connection_name  # e.g. "/cloudsql"
                )  # i.e "<PROJECT-NAME>:<INSTANCE-REGION>:<INSTANCE-NAME>"
            },
        ),
        **db_config,
    )
    pool.dialect.description_encoding = None
    logger.info("Database engine initialised from unix conection")

    return pool

Java

Spring Cloud Google Cloud PostgreSQL スターター統合を使用して、Spring JDBC ライブラリを使用する Google Cloud SQL の PostgreSQL データベースを操作します。DataSource Bean を自動的に構成するように Cloud SQL for MySQL 構成を設定します。これは、Spring JDBC と一体となり、データベースのクエリや変更などのオペレーションを可能にする JdbcTemplate オブジェクト Bean を提供します。

# Uncomment and add env vars for local development
# spring.datasource.username=${DB_USER}
# spring.datasource.password=${DB_PASSWORD}
# spring.cloud.gcp.sql.database-name=${DB_NAME}
# spring.cloud.gcp.sql.instance-connection-name=${CLOUD_SQL_CONNECTION_NAME}  
private final JdbcTemplate jdbcTemplate;

public VoteController(JdbcTemplate jdbcTemplate) {
  this.jdbcTemplate = jdbcTemplate;
}

Secret Manager で機密性の高い構成を処理する

Secret Manager を使用すると、Cloud SQL 構成などのセンシティブ データを安全に一元管理できます。このサービスは、Secret Manager から環境変数を介してランタイムに Cloud SQL 認証情報を挿入します。詳しくは、Cloud Run での シークレットの使用をご覧ください。

Node.js

// CLOUD_SQL_CREDENTIALS_SECRET is the resource ID of the secret, passed in by environment variable.
// Format: projects/PROJECT_ID/secrets/SECRET_ID/versions/VERSION
const {CLOUD_SQL_CREDENTIALS_SECRET} = process.env;
if (CLOUD_SQL_CREDENTIALS_SECRET) {
  try {
    // Parse the secret that has been added as a JSON string
    // to retrieve database credentials
    return JSON.parse(CLOUD_SQL_CREDENTIALS_SECRET.toString('utf8'));
  } catch (err) {
    throw Error(
      `Unable to parse secret from Secret Manager. Make sure that the secret is JSON formatted: ${err}`
    );
  }
}

Python

def get_cred_config() -> Dict[str, str]:
    secret = os.environ.get("CLOUD_SQL_CREDENTIALS_SECRET")
    if secret:
        return json.loads(secret)

Java

/** Retrieve config from Secret Manager */
public static HashMap<String, Object> getConfig() {
  String secret = System.getenv("CLOUD_SQL_CREDENTIALS_SECRET");
  if (secret == null) {
    throw new IllegalStateException("\"CLOUD_SQL_CREDENTIALS_SECRET\" is required.");
  }
  try {
    HashMap<String, Object> config = new Gson().fromJson(secret, HashMap.class);
    return config;
  } catch (JsonSyntaxException e) {
    logger.error(
        "Unable to parse secret from Secret Manager. Make sure that it is JSON formatted: "
            + e);
    throw new RuntimeException(
        "Unable to parse secret from Secret Manager. Make sure that it is JSON formatted.");
  }
}

サービスの配布

Identity Platform の設定

Identity Platform は、Cloud Console で手動で設定する必要があります。

  1. Cloud Console で Identity Platform の Marketplace ページに移動します。

    Identity Platform の Marketplace ページに移動

  2. [Identity Platform を有効化] をクリックします。これにより、Web client (auto created by Google Service) の名前が付された OAuth2 クライアント ID が作成されます。

  3. 生成された OAuth2 ID をダウンロードします。

    1. 新しいウィンドウで、[API とサービス] > [認証情報] ページに移動します。

      [API とサービス] > [認証情報] ページに移動

    2. 「Web client (auto created by Google Service)」のレコードでダウンロード アイコンをクリックします。

    3. ダウンロードした JSON 出力で、client_idclient_secret をメモします。

  4. Google をプロバイダとして構成します。

    1. Cloud Console で [ID プロバイダ] ページに移動します。

      [ID プロバイダ] ページに移動

    2. [プロバイダを追加] をクリックします。

    3. リストから [Google] を選択します。

    4. [Web SDK Configuration] の設定で、先ほどダウンロードした JSON の値を入力します。

      1. ウェブ クライアント ID: client_id

      2. ウェブ クライアント シークレット: client_secret

    5. [構成画面] をクリックします。

      1. ユーザータイプに [外部] を選択します。

      2. 必須項目(サポートのメールアドレス、デベロッパーのメールアドレス)に入力します。

      3. [概要] ページが表示されるまで進みます。

    6. [アプリケーションの構成] で [詳細を設定] をクリックします。スニペットをサンプルの static/config.js にコピーし、Identity Platform Client SDK を初期化します。

    7. [保存] をクリックします。

サービスのデプロイ

次の手順に沿って、インフラストラクチャのプロビジョニングおよびデプロイを完了するか、Cloud Shell で [Run on Google Cloud] をクリックしてプロセスを自動化します。

Google Cloud での実行

  1. Console または CLI を使用して、PostgSQL データベースの Cloud SQL インスタンスを作成します。

    gcloud sql instances create CLOUD_SQL_INSTANCE_NAME \
        --database-version=POSTGRES_12 \
        --region=CLOUD_SQL_REGION \
        --cpu=2 \
        --memory=7680MB \
        --root-password=DB_PASSWORD
  2. Cloud SQL の認証情報の値を postgres-secrets.json に追加します。

    Node.js

    {
      "CLOUD_SQL_CONNECTION_NAME": "PROJECT_ID:REGION:INSTANCE",
      "DB_NAME": "postgres",
      "DB_USER": "postgres",
      "DB_PASSWORD": "PASSWORD_SECRET"
    }
    

    Python

    {
      "CLOUD_SQL_CONNECTION_NAME": "PROJECT_ID:REGION:INSTANCE",
      "DB_NAME": "postgres",
      "DB_USER": "postgres",
      "DB_PASSWORD": "PASSWORD_SECRET"
    }
    

    Java

    {
      "spring.cloud.gcp.sql.instance-connection-name": "PROJECT_ID:REGION:INSTANCE",
      "spring.cloud.gcp.sql.database-name": "postgres",
      "spring.datasource.username": "postgres",
      "spring.datasource.password": "PASSWORD_SECRET"
    }

  3. Console または CLI を使用して、バージョニングされたシークレットを作成します。

    gcloud secrets create idp-sql-secrets \
        --replication-policy="automatic" \
        --data-file=postgres-secrets.json
  4. Console または CLI を使用して、サービス アカウントを作成します。

    gcloud iam service-accounts create idp-sql-identity
  5. Console または CLI を使用して、Secret Manager と Cloud SQL アクセスのバインディングを追加します。

    1. 作成したシークレットへのアクセスをサービス アカウントに許可します。

      gcloud secrets add-iam-policy-binding idp-sql-secrets \
        --member serviceAccount:idp-sql-identity@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/secretmanager.secretAccessor
    2. サービス アカウントに Cloud SQL へのアクセスを許可します。

      gcloud projects add-iam-policy-binding PROJECT_ID \
        --member serviceAccount:idp-sql-identity@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/cloudsql.client
  6. Cloud Build を使用してコンテナ イメージをビルドします。

    Node.js

    gcloud builds submit --tag gcr.io/PROJECT_ID/idp-sql

    Python

    gcloud builds submit --tag gcr.io/PROJECT_ID/idp-sql

    Java

    このサンプルでは、Jib を使用して一般的な Java ツールにより Docker イメージをビルドします。Jib は、Dockerfile や Docker をインストールせずにコンテナのビルドを最適化します。Jib を使用して Java コンテナを構築する方法の詳細を確認します。

    1. Docker を承認して Container Registry に push するには、gcloud 認証ヘルパーを使用します。

      gcloud auth configure-docker

    2. Jib Maven プラグインを使用して、コンテナをビルドして Container Registry に push します。

      mvn compile jib:build -Dimage=gcr.io/PROJECT_ID/idp-sql

  7. Console または CLI を使用して、コンテナ イメージを Cloud Run にデプロイします。

    gcloud beta run deploy idp-sql \
        --image gcr.io/PROJECT_ID/idp-sql \
        --allow-unauthenticated \
        --service-account idp-sql-identity@PROJECT_ID.iam.gserviceaccount.com \
        --add-cloudsql-instances PROJECT_ID:REGION:CLOUD_SQL_INSTANCE_NAME \
        --update-secrets CLOUD_SQL_CREDENTIALS_SECRET=idp-sql-secrets:latest

    具体的には、--service-account--add-cloudsql-instances--update-secrets フラグを使用して、サービス ID、Cloud SQL インスタンス接続、シークレット名(環境変数としてバージョンを指定)をそれぞれ指定します。

最後の仕上げ

ユーザーのログイン後に、許可されたリダイレクトとして Cloud Run サービスの URL を承認します。

  1. [ID プロバイダ] ページでペンのアイコンをクリックして、Google プロバイダを編集します。

  2. [承認済みドメイン] で [ドメインを追加] をクリックし、Cloud Run サービスの URL を入力します。

    ビルドまたはデプロイの後、サービス URL はログで確認できます。また、次のコマンドを使用して確認することもできます。

    gcloud run services describe idp-sql --format 'value(status.url)'

試してみる

完成したサービスを試すには:

  1. ブラウザで、前述のデプロイの手順により提供された URL に移動します。

  2. [Google でログイン] ボタンをクリックして、認証フローを行います。

  3. 投票します。

    次のようになります。

    ユーザー インターフェースのスクリーンショットには、各チームへの投票数と投票の一覧が示されます。

これらのサービスを開発し続けることにした場合、Google Cloud の他のサービスへの Identity and Access Management(IAM)アクセスが制限されます。他の多くのサービスにアクセスするには、追加の IAM ロールをこれらのサービスに与える必要があることにご注意ください。

クリーンアップ

このチュートリアル用に新規プロジェクトを作成した場合は、そのプロジェクトを削除します。既存のプロジェクトを使用し、このチュートリアルで変更を加えずに残す場合は、チュートリアル用に作成したリソースを削除します。

プロジェクトを削除する

課金をなくす最も簡単な方法は、チュートリアル用に作成したプロジェクトを削除することです。

プロジェクトを削除するには:

  1. Cloud Console で [リソースの管理] ページに移動します。

    [リソースの管理] に移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

チュートリアル リソースを削除する

  1. このチュートリアルでデプロイした Cloud Run サービスを削除します。

    gcloud run services delete SERVICE-NAME

    SERVICE-NAME は、選択したサービス名です。

    Cloud Run サービスは Google Cloud Console から削除することもできます。

  2. チュートリアルの設定時に追加した gcloud のデフォルト リージョン構成を削除します。

     gcloud config unset run/region
    
  3. プロジェクト構成を削除します。

     gcloud config unset project
    
  4. このチュートリアルで作成した他の Google Cloud リソースを削除します。

次のステップ