VPC Service Controls 準拠のプライベート エンドポイントを呼び出す

Workflows で Service Directory のサービス レジストリを使用すると、ワークフローの実行から HTTP 呼び出しのプライベート エンドポイントをターゲットにできます。Virtual Private Cloud(VPC)ネットワーク内にプライベート エンドポイントを作成することで、エンドポイントを VPC Service Controls に準拠させることが可能です。

VPC Service Controls によって、Identity and Access Management(IAM)から独立している追加のセキュリティ防御レイヤが提供されます。IAM では詳細な ID ベースのアクセス制御が可能ですが、VPC Service Controls では、境界全体での下り(外向き)データの制御など、コンテキスト ベースの境界セキュリティが可能になります。

  • Service Directory は、登録済みネットワーク サービスに関する情報(名前、ロケーション、属性など)を保存するサービス レジストリです。インフラストラクチャに関係なく、サービスを自動的に登録して、詳細情報を取得できます。これにより、すべてのサービス エンドポイントで大規模なサービスを検出、公開、接続できます。

  • VPC ネットワークは、仮想マシン(VM)インスタンスに接続性を提供し、内部 IP アドレスを使用して VPC ネットワーク内にプライベート エンドポイントを作成できるようにします。VPC ネットワーク リソースへの HTTP 呼び出しは、IAM と VPC Service Controls を適用しながら、プライベート ネットワーク経由で送信されます。

  • VPC Service Controls は、サービス境界の設定とデータ転送の境界の作成を可能にする、Google Cloud の機能です。VPC Service Controls を Workflows とともに使用すると、サービスを保護し、データ漏洩のリスクを軽減できます。

このドキュメントでは、VPC ネットワーク内の VM を Service Directory エンドポイントとして登録する方法について説明します。これにより、ワークフローに Service Directory サービス名を指定できます。ワークフローの実行では、サービス レジストリから取得した情報を使用して、公共のネットワークに出ることなく、適切な HTTP リクエストを送信します。

次の図に概要を示します。

Service Directory の情報を使用して、VM インスタンスのポート番号に HTTP リクエストを送信する

大まかには以下を行う必要があります。

  1. Cloud Workflows サービス エージェントに権限を付与して、サービス エージェントが Service Directory リソースを表示し、Service Directory を使用して VPC ネットワークにアクセスできるようにします。
  2. ネットワーク機能を提供する VPC ネットワークを作成します。
  3. VPC ファイアウォール ルールを作成して、VPC ネットワーク内の VM インスタンスとの間で送受信されるトラフィックを許可または拒否できるようにします。
  4. VPC ネットワークに VM インスタンスを作成します。Compute Engine VM インスタンスは、Google のインフラストラクチャでホストされる仮想マシンです。Compute Engine インスタンス、VM インスタンス、VM という用語は同義語であり、同じ意味で使用されています。
  5. VM にアプリケーションをデプロイします。VM インスタンスでアプリを実行して、トラフィックが想定どおりに処理されていることを確認できます。
  6. ワークフローの実行で Service Directory エンドポイントを呼び出せるように、Service Directory を構成します。
  7. ワークフローを作成してデプロイします。ワークフローの private_service_name 値は、前の手順で登録した Service Directory エンドポイントを指定します。

Cloud Workflows サービス エージェントに権限を付与する

一部の Google Cloud サービスには、ユーザーのリソースへのアクセスを許可するサービス エージェントがあります。API にサービス エージェントが必要な場合は、API を有効にして使用した後、サービス エージェントが作成されます。

  1. 最初のワークフローをデプロイすると、Cloud Workflows サービス エージェントが次の形式で自動的に作成されます。

    service-PROJECT_NUMBER@gcp-sa-workflows.iam.gserviceaccount.com

    次のコマンドを使用して、ワークフローを使用せずにプロジェクトにサービス アカウントを手動で作成できます。

    gcloud beta services identity create \
        --service=workflows.googleapis.com \
        --project=PROJECT_ID

    PROJECT_ID は、実際の Google Cloud プロジェクト ID に置き換えます。

  2. Service Directory リソースを表示するには、プロジェクトの Service Directory 閲覧者のロールservicedirectory.viewer)を Workflows サービス エージェントに付与します。

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member=serviceAccount:service-PROJECT_NUMBER@gcp-sa-workflows.iam.gserviceaccount.com \
        --role=roles/servicedirectory.viewer

    PROJECT_NUMBER は、実際の Google Cloud プロジェクトの番号に置き換えます。プロジェクト番号は、Google Cloud コンソールの [ようこそ] ページで確認できます。また、次のコマンドで確認することもできます。

    gcloud projects describe PROJECT_ID --format='value(projectNumber)'
  3. Service Directory を使用して VPC ネットワークにアクセスするには、プロジェクトの Private Service Connect の承認済みサービスのロールroles/servicedirectory.pscAuthorizedService)を Workflows サービス エージェントに付与します。

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member=serviceAccount:service-PROJECT_NUMBER@gcp-sa-workflows.iam.gserviceaccount.com \
        --role=roles/servicedirectory.pscAuthorizedService

VPC ネットワークの作成

VPC ネットワークは、Google の本番環境ネットワーク内に仮想的に実装された物理ネットワークです。Compute Engine VM インスタンスへの接続性を提供します。

自動モードまたはカスタムモードの VPC ネットワークを作成できます。新しく作成した各ネットワークには、同じプロジェクト内で一意の名前を付ける必要があります。

たとえば、次のコマンドは自動モード VPC ネットワークを作成します。

gcloud compute networks create NETWORK_NAME \
    --subnet-mode=auto

NETWORK_NAME は VPC ネットワークの名前に置き換えます。

詳細については、VPC ネットワークを作成して管理するをご覧ください。

VPC ファイアウォール ルールを作成する

VPC ファイアウォール ルールを使用すると、ポート番号、タグ、プロトコルに基づいて、VPC ネットワーク内の VM インスタンスとの間で送受信されるトラフィックを許可または拒否できます。

VPC ファイアウォール ルールはネットワーク レベルで定義され、ルールが作成されたネットワークにのみ適用されます。ただし、ルールに使用する名前はプロジェクトごとに一意である必要があります。

たとえば、次のコマンドは、指定された VPC ネットワークに対してファイアウォール ルールを作成し、任意の IPv4 アドレス(0.0.0.0/0)からの上り(内向き)トラフィックを許可します。--rules フラグの値を all にすると、すべてのプロトコルと宛先ポートにルールが適用されます。

gcloud compute firewall-rules create RULE_NAME \
    --network=projects/PROJECT_ID/global/networks/NETWORK_NAME \
    --direction=INGRESS \
    --action=ALLOW \
    --source-ranges=0.0.0.0/0 \
    --rules=all

RULE_NAME の部分は、ファイアウォール ルールの名前に置き換えます。

詳細については、VPC ファイアウォール ルールをご覧ください。

VPC ネットワーク内に VM インスタンスを作成する

VM インスタンスには、Google Kubernetes Engine(GKE)クラスタ、App Engine フレキシブル環境インスタンス、Compute Engine VM 上に構築された他の Google Cloud プロダクトが含まれます。プライベート ネットワーク アクセスをサポートするために、VPC ネットワーク リソースは、VM インスタンス、Cloud Interconnect IP アドレス、またはレイヤ 4 内部ロードバランサにできます。

Compute Engine インスタンスでは、Google が提供する Linux 用または Windows Server 用の公開イメージだけでなく、独自に作成したか既存のシステムからインポートした非公開のカスタム イメージも実行できます。Docker コンテナをデプロイすることもできます。

インスタンスのマシン プロパティ(仮想 CPU の数やメモリの容量など)を選択するには、事前定義されたマシンタイプのセットを使用するか、または独自のカスタム マシンタイプを作成します。

たとえば、次のコマンドは、以前に作成した VPC ネットワークに接続されたネットワーク インターフェースを持つ公開イメージから Linux VM インスタンスを作成します。

  1. VM インスタンスを作成して起動します。

    gcloud compute instances create VM_NAME \
        --image-family=debian-11 \
        --image-project=debian-cloud \
        --machine-type=e2-micro \
        --network-interface network=projects/PROJECT_ID/global/networks/NETWORK_NAME

    VM_NAME は VM の名前に置き換えます。

  2. インスタンスのゾーンを確認するように求められたら、「y」と入力します。

    VM インスタンスを作成したら、返される INTERNAL_IP アドレスをメモします。

  3. Google Cloud コンソールで [VM インスタンス] ページに移動します。

    [VM インスタンス] に移動

  4. [名前] 列で、該当する VM インスタンスの名前をクリックします。

  5. VM が実行されている場合は、 [停止] をクリックして VM を停止します。

  6. VM を編集するには、 [編集] をクリックします。

  7. [ネットワーキング] > [ファイアウォール] セクションで、VM への HTTP または HTTPS トラフィックを許可するには、[HTTP トラフィックを許可する] または [HTTPS トラフィックを許可する] を選択します。

    この例では、[HTTP トラフィックを許可する] チェックボックスをオンにします。

    Compute Engine はネットワーク タグを VM に追加し、ファイアウォール ルールを VM に関連付けます。次に、対応する上り(内向き)ファイアウォール ルールを作成し、tcp:80(HTTP)または tcp:443(HTTPS)で受信するすべてのトラフィックを許可します。

  8. 変更を保存するには、[保存] をクリックします。

  9. VM を再起動するには、[開始 / 再開] をクリックします。

詳しくは、VM インスタンスの作成と開始をご覧ください。

VM にアプリケーションをデプロイする

ネットワーク構成をテストし、トラフィックが想定どおりに処理されていることを確認するには、VM にポートをリッスンするシンプルなアプリをデプロイできます。

たとえば、次のコマンドはポート 3000 でリッスンする Node.js ウェブサービスを作成します。

  1. VM インスタンスへの SSH 接続を確立します。

  2. パッケージ リポジトリを更新します。

    sudo apt update
  3. NVMNode.jsnpm をインストールします。

    詳細については、Node.js 開発環境の設定をご覧ください。

  4. package.json ファイルをインタラクティブに作成します。

    npm init

    次に例を示します。

    {
    "name": "test",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
    "test": "hello"
    },
    "author": "",
    "license": "ISC"
    }
  5. Node.js 用のウェブ アプリケーション フレームワークである Express をインストールします。

    npm install express
  6. テストアプリのコードを作成します。

    vim app.js

    次のサンプルでは、ルートパス(/)への GET リクエストに「Hello, world!」というテキストで応答するアプリを作成します。

    const express = require('express');
    const app = express();
    
    app.get('/', (req, res) => {
      res.status(200).send('Hello, world!').end();
    });
    
    app.listen(3000, () => {
      console.log('Sample app listening on port 3000.');
    });

    アプリがリッスンしているポートをメモします。Service Directory サービスのエンドポイントを構成する際は、同じポート番号を使用する必要があります。

  7. アプリがポート 3000 でリッスンしていることを確認します。

    node app.js

Compute Engine にはさまざまなデプロイ オプションが用意されています。詳細については、ワークロードに対する Compute Engine のデプロイ形態を選択するをご覧ください。

Service Directory を構成する

ワークフローの実行からプライベート エンドポイントの呼び出しをサポートするには、Service Directory の名前空間を設定し、名前空間にサービスを登録して、サービスにエンドポイントを追加する必要があります。

たとえば、次のコマンドは、VM インスタンスの VPC ネットワークと内部 IP アドレスを指定する名前空間、サービス、エンドポイントを作成します。

  1. Namespace を作成します。

    gcloud service-directory namespaces create NAMESPACE \
        --location=REGION
    

    以下を置き換えます。

    • NAMESPACE: 名前空間の ID または名前空間の完全修飾識別子。
    • REGION: 名前空間を含む Google Cloud リージョン。例: us-central1
  2. サービスを作成します。

    gcloud service-directory services create SERVICE \
        --namespace=NAMESPACE \
        --location=REGION
    

    SERVICE は、作成するサービスの名前に置き換えます。

  3. エンドポイントを構成します。

    gcloud service-directory endpoints create ENDPOINT \
        --namespace=NAMESPACE \
        --service=SERVICE \
        --network=projects/PROJECT_NUMBER/locations/global/networks/NETWORK_NAME \
        --port=PORT_NUMBER \
        --address=IP_ADDRESS \
        --location=REGION
    

    以下を置き換えます。

    • ENDPOINT: 作成するエンドポイントの名前。
    • PORT_NUMBER: エンドポイントが実行されているポート。例: 3000
    • IP_ADDRESS: エンドポイントの IPv6 アドレスまたは IPv4 アドレス。これは、以前にメモした内部 IP アドレスです。

詳細については、Service Directory の構成プライベート ネットワーク アクセスの構成をご覧ください。

ワークフローを作成してデプロイする

Workflows からのプライベート エンドポイントの呼び出しは、HTTP リクエストを介して行われます。最も一般的な HTTP リクエスト メソッドには、呼び出しショートカット(http.gethttp.post など)がありますが、call フィールドを http.request に設定し、method フィールドでリクエストのタイプを指定することであらゆるタイプの HTTP リクエストを作成できます。詳細については、HTTP リクエストを行うをご覧ください。

  1. ワークフローのソースコード ファイルを作成します。

    touch call-private-endpoint.JSON_OR_YAML
    

    JSON_OR_YAML は、ワークフローの形式に応じて yaml または json に置き換えます。

  2. テキスト エディタで、次のワークフロー(この場合は url 値に HTTP プロトコルを使用)をソースコード ファイルにコピーします。

    YAML

    main:
      steps:
        - checkHttp:
            call: http.get
            args:
              url: http://IP_ADDRESS
              private_service_name: "projects/PROJECT_ID/locations/REGION/namespaces/NAMESPACE/services/SERVICE"
            result: res
        - ret:
            return: ${res}

    JSON

    {
      "main": {
        "steps": [
          {
            "checkHttp": {
              "call": "http.get",
              "args": {
                "url": "http://IP_ADDRESS",
                "private_service_name": "projects/PROJECT_ID/locations/REGION/namespaces/NAMESPACE/services/SERVICE"
              },
              "result": "res"
            }
          },
          {
            "ret": {
              "return": "${res}"
            }
          }
        ]
      }
    }

    private_service_name 値は、登録済の Service Directory サービス名を次の形式で指定する文字列にする必要があります。

    projects/PROJECT_ID/locations/LOCATION/namespaces/NAMESPACE_NAME/services/SERVICE_NAME

  3. ワークフローをデプロイします。テスト目的で、ワークフローに Compute Engine のデフォルトのサービス アカウントを関連付けて、その ID を示すことができます。

    gcloud workflows deploy call-private-endpoint \
        --source=call-private-endpoint.JSON_OR_YAML \
        --location=REGION \
        --service-account=PROJECT_NUMBER-compute@developer.gserviceaccount.com
    
  4. ワークフローを実行します。

    gcloud workflows run call-private-endpoint \
        --location=REGION

    次のような結果が表示されます。

    argument: 'null'
    duration: 0.650784403s
    endTime: '2023-06-09T18:19:52.570690079Z'
    name: projects/968807934019/locations/us-central1/workflows/call-private-endpoint/executions/4aac88d3-0b54-419b-b364-b6eb973cc932
    result: '{"body":"Hello, world!","code":200,"headers":{"Connection":"keep-alive","Content-Length":"21","Content-Type":"text/html;
    charset=utf-8","Date":"Fri, 09 Jun 2023 18:19:52 GMT","Etag":"W/\"15-NFaeBgdti+9S7zm5kAdSuGJQm6Q\"","Keep-Alive":"timeout=5","X-Powered-By":"Express"}}'
    startTime: '2023-06-09T18:19:51.919905676Z'
    state: SUCCEEDED
    

次のステップ