トラブルシューティング

このページでは、VPC の構成で発生する可能性がある問題について説明します。

VPC Service Controls のエラーを探す

このセクションでは、監査ログで VPC エラーを検出する 2 つの方法について説明します。エラーの検出には、一意の ID を使用するか、メタデータを使用します。

エラーの一意の ID を使用する

VPC Service Controls によって生成されるエラーには、関連する監査ログを識別するために使用される一意の ID が含まれます。

以下の説明では、Logging のドキュメントに記載されている用語を使用します。詳細については、基本ログフィルタをご覧ください。

一意の ID を使用してエラーに関する情報を取得するには:

  1. Cloud Console で、エラーの原因と考えられるサービス境界内のプロジェクトの Stackdriver Logging ページに移動します。

    [Stackdriver Logging] ページに移動

  2. 検索フィルタ ボックスに、エラーの一意の ID を入力します。

メタデータを使用してログをフィルタする

VPC Service Controls に関連するエラーを見つけるには、Cloud Loggingを使用してください。

Console

以下の説明では、Logging のドキュメントに記載されている用語を使用します。詳細については、基本ログフィルタをご覧ください。

過去 24 時間に発生した VPC Service Controls のエラーを Logging で探すには以下の手順に従ってください。

  1. Google Cloud Console で、サービス境界内のプロジェクトのStackdriver Logging ページに移動します。

    [Stackdriver Logging] ページに移動

  2. 検索フィルタ ボックスに、次のように入力します。

    protoPayload.metadata.@type:"type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
        
  3. リソースの基本セレクタ メニューで、[監査対象リソース] を選択します。

  4. 時間範囲セレクタのプルダウン メニューで、[過去 24 時間] を選択します。

  5. 別の期間に発生した VPC Service Controls のエラーを探す場合は、時間範囲セレクタ プルダウン メニューで範囲を変更します。

gcloud

過去 24 時間の VPC Service Controls のエラーを確認するには、次のコマンドを使用します。

gcloud logging read 'protoPayload.metadata.@type:"type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"'
    

デフォルトでは、read コマンドは過去 24 時間に制限されています。別の期間の VPC Service Controls のログを取得するには、次のいずれかのコマンドを使用します。

現在の日付を基準にしてログを制限するには次のコマンドを使用します。

gcloud logging read \
      'protoPayload.metadata.@type:"type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"' \
      --freshness=DURATION
    

ここで

  • DURATION は形式化された期間です。フォーマットの詳細については、gcloud相対期間 / 時間形式をご覧ください。

たとえば、先週発生したすべての VPC Service Controls エラーを取得するには、次のように入力します。

gcloud logging read \
      'protoPayload.metadata.@type:"type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"' \
      --freshness=7d
    

一定期間ログを制限するには次のコマンドを使用します。

gcloud logging read \
      'protoPayload.metadata.@type:"type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata" AND
      timestamp>="DATETIME" AND
      timestamp<="DATETIME"'
    

ここで

  • DATETIME は、書式付きの日付 / 時刻文字列です。フォーマットの詳細については、gcloud絶対日付 / 時刻形式をご覧ください。

たとえば、2019 年 3 月 22 日から 2019 年 3 月 26 日までに発生したすべての VPC Service Controls エラーを取得するには、次のように入力します。

gcloud logging read \
      'protoPayload.metadata.@type:"type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata" AND
      timestamp>="2019-03-22T23:59:59Z" AND
      timestamp<="2019-03-26T00:00:00Z"'
    

サポートされていないサービス

VPC Service Controls でサポートされているプロダクトとサービスについては、サポートされているプロダクトページをご覧ください。

サポートされていないサービスを gcloud コマンドライン ツールまたは Access Context Manager API で制限しようとするとエラーが発生します。

サポートされているサービスのデータに対するプロジェクト間のアクセスは、VPC Service Controls によってブロックされます。 また、制限付き VIP を使用して、サポートされていないサービスを呼び出すワークロードをブロックできます。

共有 VPC

共有 VPC を使用する場合、共有 VPC ネットワークに属するプロジェクトを含むサービス境界には、ネットワークのホストプロジェクトも含める必要があります。 共有 VPC ネットワークに属するプロジェクトがホスト プロジェクトと同じ境界にない場合、サービスは期待どおりに動作しないか、完全にブロックされます。

共有 VPC ネットワーク ホストが、ネットワークに接続されているプロジェクトと同じサービス境界にあることを確認します。

境界間のリクエスト

通常、アクセスレベルは、境界内部の保護されたリソースに対し、サービス境界の外部からのリクエストを許可するために使用されます。

ただし、別の境界内の保護されたリソースに対する境界内のプロジェクトからのリクエストは、アクセスレベルで通常はリクエストが許可される場合でも拒否されます。

たとえば、境界 1 のプロジェクト A がプロジェクト B からリソースをリクエストするとします。 プロジェクト B のリソースは境界 2 によって保護されています。プロジェクト A は境界内にあるため、通常、境界 2 のアクセスレベルで保護されたリソースのリクエストが許可される場合でも、リクエストは拒否されます。

境界間でリクエストを処理するには、次の 2 つの方法があります。

  • 境界ブリッジを使用します。ブリッジでは、異なる境界内の 2 つ以上のプロジェクトが、それらのプロジェクト内のすべてのサービスにリクエストを送信できます。これらのリクエストは、サービスが境界によって保護されていても許可されます。

  • リクエスト元のサービスとターゲット リソースの両方が境界によって保護されていないことを確認します。このシナリオでは、サービスは保護されていないため、操作は成功します。

エラーの原因が VPC Service Controls かどうか判断する

VPC Service Controls は Google Cloud の特定の低レベル プロパティを変更するため、複数のサービスに影響が連鎖する可能性があります。このため、調査の範囲を明確にしないとデバッグが難しくなります。

VPC Service Controls に起因するエラーかどうかを特定するには、VPC Service Controls が有効で、使用するプロジェクトとサービスに適用されているかどうかを確認します。これは、gcloud コマンドライン ツールまたは Cloud Console で行うことができます。

サービス境界内のプロジェクトで VPC Service Controls が制限付きサービスに設定しているサービスを使用している場合(別のサービスから間接的に使用されるサービスも含む)、VPC Service Controls に起因する問題と考えられます。

既知の問題の事例については、サービスに関する既知の制限事項をご覧ください。

通常、サービスは依存関係に従ってエラー メッセージを伝播します。次のエラーのいずれかが発生した場合、VPC Service Controls に問題があります。

  • Cloud Storage: 403: Request violates VPC Service Controls.

  • BigQuery: 403: VPC Service Controls: Request is prohibited by organization's policy.

  • その他のサービス: 403: Request is prohibited by organization's policy.

VPC Service Controls が予期しない理由でブロックしたリクエストをデバッグする

VPC Service Controls がリクエストをブロックした理由を調査する場合、VPC Service Controls の監査ログが基本的なツールとなります。

通常、アクセスが予期せずにブロックされた場合は、プロジェクトの監査ログでリクエストの送信元を確認します。このログには、リクエストされたリソースやリクエストが拒否された理由に関する重要なデータが記録されています。

ログの詳細については、ログの表示をご覧ください。

次の表は、PC Service Controls の使用時に発生する可能性のある violationReason の値を示します。

violationReason 説明
RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER 監査ログレコードの resourceNames の下にあるリソースは、同じサービス境界内にありません。
NETWORK_NOT_IN_SAME_SERVICE_PERIMETER callerNetworkresourceNames に対応するリソースは、同じサービス境界内にありません。
NO_MATCHING_ACCESS_LEVEL

監査ログレコード内の callerIp に対応する IP アドレスが、サービス境界に割り当てられたアクセスレベルの IP 範囲と一致しません。

サンプル事例

以下では、VPC Service Controls の使用中に発生する可能性があるシナリオについて説明します。

オンプレミスからの Cloud Storage へのアクセス

この例では、従業員のワークステーションからプロジェクト corp-storage の Cloud Storage バケットへのリクエスト(callerIp によって識別されたもの)は、VPC Service Controls によってブロックされます。

このリクエストにより、次の監査ログレコードが生成されます。

{
     insertId:  "222lvajc6f7"
     logName:  "projects/corp-storage/logs/cloudaudit.googleapis.com%2Fpolicy"
     protoPayload: {
      @type:  "type.googleapis.com/google.cloud.audit.AuditLog"
      authenticationInfo: {
       principalEmail:  "someone@google.com"
      }
      metadata: {
       @type:  "type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
       resourceNames: [
        0:  "projects/_"
       ]
       violationReason:  "NO_MATCHING_ACCESS_LEVEL"
      }
      methodName:  "google.storage.NoBillingOk"
      requestMetadata: {
       callerIp:  "b1d5:d26d:5b17:43fe:d358:586b:db59:9617"
       destinationAttributes: {
       }
       requestAttributes: {
       }
      }
      resourceName:  "projects/690885588241"
      serviceName:  "storage.googleapis.com"
      status: {
       code:  7
       details: [
        0: {
         @type:  "type.googleapis.com/google.rpc.PreconditionFailure"
         violations: [
          0: {
           type:  "VPC_SERVICE_CONTROLS"
          }
         ]
        }
       ]
       message:  "Request is prohibited by organization's policy"
      }
     }
     receiveTimestamp:  "2018-11-27T21:40:43.823209571Z"
     resource: {
      labels: {
       method:  "google.storage.NoBillingOk"
       project_id:  "corp-storage"
       service:  "storage.googleapis.com"
      }
      type:  "audited_resource"
     }
     severity:  "ERROR"
     timestamp:  "2018-11-27T21:40:42.973784140Z"
    }
    

corp-storage プロジェクトはサービス境界に含まれています。従業員のワークステーションは、境界内のネットワークに接続していません。従業員のワークステーションは境界の外側にあるため、リクエストがブロックされます。

プロジェクト外の VM から BigQuery へのアクセス

この例では、プロジェクト 458854174376data-collector)に属する VM は、プロジェクト 798816221974corp-resources-protected)内のデータセットに対して BigQuery クエリを実行しようとしますが、拒否されます。

VM は次のクエリを使用します。

bq --project=corp-resources-protected query 'select count(*) from babynames.yob2000'
    

クエリから次の結果が返されます。

BigQuery error in query operation: VPC Service Controls: Request is
    prohibited by organization's policy. Operation ID:
    33643962-6a0f-4091-9283-bcdf7e9271f0
    

次の監査ログレコードが生成されます。

{
     insertId:  "1ei551d2pdq"
     logName:  "projects/corp-resources-protected/logs/cloudaudit.googleapis.com%2Fpolicy"
     protoPayload: {
      @type:  "type.googleapis.com/google.cloud.audit.AuditLog"
      authenticationInfo: {
       principalEmail:  "714877721106-compute@example.gserviceaccount.com"
      }
      metadata: {
       @type:  "type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
       resourceNames: [
        0:  "projects/1004338142803"
       ]
       violationReason:  "NETWORK_NOT_IN_SAME_SERVICE_PERIMETER"
      }
      methodName:  "bigquery.googleapis.com/bigquery.jobs.create"
      requestMetadata: {
       callerIp:  "10.105.0.2"
       callerNetwork:  "//compute.googleapis.com/projects/ameet-dataflow/global/networks/__unknown__"
       destinationAttributes: {
       }
       requestAttributes: {
       }
      }
      resourceName:  "projects/1004338142803"
      serviceName:  "bigquery.googleapis.com"
      status: {
       code:  7
       details: [
        0: {
         @type:  "type.googleapis.com/google.rpc.PreconditionFailure"
         violations: [
          0: {
           type:  "VPC_SERVICE_CONTROLS"
          }
         ]
        }
       ]
       message:  "Request is prohibited by organization's policy"
      }
     }
     receiveTimestamp:  "2018-11-28T23:06:13.579882505Z"
     resource: {
      labels: {
       method:  "bigquery.googleapis.com/bigquery.jobs.create"
       project_id:  "corp-resources-protected"
       service:  "bigquery.googleapis.com"
      }
      type:  "audited_resource"
     }
     severity:  "ERROR"
     timestamp:  "2018-11-28T23:06:12.799656975Z"
    }
    

この例では、violationReasonNETWORK_NOT_IN_SAME_SERVICE_PERIMETER です。callerIp の他に callerNetwork が含まれています。IP アドレスはプライベートであり、曖昧さを解消するためにネットワークが使用されています。ここで問題に関連するリソースが VpcServiceControlAuditMetadata.resourceNamesrequestMetadata.callerNetwork (ネットワークを所有するプロジェクト)の 2 つの場所に記録されています。

corp-resources-protected プロジェクトがサービス境界内にあり、VM が所属するネットワークのプロジェクト data-collector が同じ境界内に存在しないため、エラーが発生しています。この場合、アクセスの拒否は想定どおりの結果です。

プロジェクト間の BigQuery クエリ

この例では、perimeter-network プロジェクトに属する VM は、perimeter-network と同じサービス境界内に存在するプロジェクト corp-resources-protected と存在しないプロジェクト corp-resources-public の2 つの異なるプロジェクトの BigQuery インスタンスを照会します。

VM は次のコマンドを使用します。

bq query --use_legacy_sql=false \
      'select count(priv.name),count(pub.name) from \
      `corp-resources-protected.babynames.yob2000` as priv, \
      `corp-resources-public.babynames.yob2000` as pub'
    

クエリから次の結果が返されます。

BigQuery error in query operation: Error processing job
    'example:bqjob_r211e6f6eec928ffb_000001675c996aa8_1': VPC Service Controls:
    Request is prohibited by organization's policy. Operation ID:
    dc4fc177-4850-4fc5-b2e7-8c33f302149a
    

次の監査ログレコードが生成されます。

{
     insertId:  "17kg4exd24ag"
     logName:  "projects/perimeter-network/logs/cloudaudit.googleapis.com%2Fpolicy"
     protoPayload: {
      @type:  "type.googleapis.com/google.cloud.audit.AuditLog"
      authenticationInfo: {
      }
      metadata: {
       @type:  "type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
       resourceNames: [
        0:  "projects/117961063178"
        1:  "projects/690885588241"
       ]
       violationReason:  "RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER"
      }
      methodName:  "bigquery.googleapis.com/bigquery.tables.getData"
      requestMetadata: {
       callerIp:  "130.211.225.66"
       callerNetwork:  "//compute.googleapis.com/projects/perimeter-network/global/networks/__unknown__"
       destinationAttributes: {
       }
       requestAttributes: {
       }
      }
      resourceName:  "projects/927005422713"
      serviceName:  "bigquery.googleapis.com"
      status: {
       code:  7
       details: [
        0: {
         @type:  "type.googleapis.com/google.rpc.PreconditionFailure"
         violations: [
          0: {
           type:  "VPC_SERVICE_CONTROLS"
          }
         ]
        }
       ]
       message:  "Request is prohibited by organization's policy"
      }
     }
     receiveTimestamp:  "2018-11-28T20:48:51.384237810Z"
     resource: {
      labels: {
       method:  "bigquery.googleapis.com/bigquery.tables.getData"
       project_id:  "perimeter-network"
       service:  "bigquery.googleapis.com"
      }
      type:  "audited_resource"
     }
     severity:  "ERROR"
     timestamp:  "2018-11-28T20:48:50.561884949Z"
    }
    

callerNetworkVpcServiceControlAuditMetadata.resourceNames を見ると、perimeter-network117961063178corp-resources-public)、690885588241corp-resources-protected)の 3 つのプロジェクトがあります。corp-resources-public は、perimeter-networkcorp-resources-protected と同じサービス境界内に存在しません。

violationReasonRESOURCES_NOT_IN_SAME_SERVICE_PERIMETER の場合、リクエストの一部のリソースが、リクエストに適用される境界の外側にあることを意味しています。この場合、corp-resources-public が境界外のリソースです。

境界内の VM から Cloud Storage へのファイルの移動

この例では、プロジェクト perimeter-network 内の VM がコマンドを実行して、プロジェクト corp-resources-protected の 1 つの Cloud Storage バケットからプロジェクト corp-resources-public のバケットにファイルを移動しようとしています。

VM は次のコマンドを使用します。

gsutil mv gs://corp-resources-private-1/yob2000.txt gs://corp-resources-public-1/babynames/
    

次の結果が返されます。

Copying gs://corp-resources-private-1/yob2000.txt [Content-Type=text/plain]...
    AccessDeniedException: 403 Request violates VPC Service Controls.
    

次の監査ログレコードが生成されます。

{
     insertId:  "1xxnssmd2hqo"
     logName:  "projects/perimeter-network/logs/cloudaudit.googleapis.com%2Fpolicy"
     protoPayload: {
      @type:  "type.googleapis.com/google.cloud.audit.AuditLog"
      authenticationInfo: {
       principalEmail:  "storage-accessing@example.iam.gserviceaccount.com"
      }
      metadata: {
       @type:  "type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
       resourceNames: [
        0:  "projects/_/buckets/corp-resources-public-1"
       ]
       violationReason:  "NETWORK_NOT_IN_SAME_SERVICE_PERIMETER"
      }
      methodName:  "google.storage.BillingRequiredRead"
      requestMetadata: {
       callerIp:  "130.211.225.66"
       callerNetwork:  "//compute.googleapis.com/projects/perimeter-network/global/networks/__unknown__"
       destinationAttributes: {
       }
       requestAttributes: {
       }
      }
      resourceName:  "projects/927005422713"
      serviceName:  "storage.googleapis.com"
      status: {…}
     }
     receiveTimestamp:  "2018-11-28T00:45:31.531623485Z"
     resource: {
      labels: {
       method:  "google.storage.BillingRequiredRead"
       project_id:  "perimeter-network"
       service:  "storage.googleapis.com"
      }
      type:  "audited_resource"
     }
     severity:  "ERROR"
     timestamp:  "2018-11-28T00:45:31.351140381Z"
    }
    

この場合、メソッドが BillingRequiredRead で、実行されたアクションが move のため、ログの内容が明確ではありません。これは、VPC Service Controls の現在の監査ログ機能の制限です。

理由は明確ではありませんが、この監査ログレコードは、リクエストの一部のリソースがリクエストに適用される境界の外側にあることを意味しています。この場合、corp-resources-public が境界外のリソースです。

境界外の VM から Cloud Storage へのファイルの移動

この例では、プロジェクト public-network 内の VM がコマンドを実行して、プロジェクト corp-resources-protected の 1 つの Cloud Storage バケットからプロジェクト corp-resources-public のバケットにファイルを移動しようとしています。

corp-resources-protected はサービス境界によって保護されています。public-networkcorp-resources-public はこの境界の外側に存在します。

VM は次のコマンドを使用します。

gsutil mv gs://corp-resources-private-1/yob2000.txt gs://corp-resources-public-1/babynames/
    

次の結果が返されます。

Copying gs://corp-resources-private-1/yob2000.txt [Content-Type=text/plain]...
    AccessDeniedException: 403 Request violates VPC Service Controls.
    

次の監査ログレコードが生成されます。

{
     insertId:  "10moqhsch9v"
     logName:  "projects/corp-resources-private/logs/cloudaudit.googleapis.com%2Fpolicy"
     protoPayload: {
      @type:  "type.googleapis.com/google.cloud.audit.AuditLog"
      authenticationInfo: {
       principalEmail:  "user@example.biz"
      }
      metadata: {
       @type:  "type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
       resourceNames: [
        0:  "projects/_/buckets/corp-resources-private-1/objects/yob2000.txt"
        1:  "projects/_/buckets/corp-resources-public-1/objects/out.txt"
       ]
       violationReason:  "RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER"
      }
      methodName:  "google.storage.Write"
      requestMetadata: {
       callerIp:  "2620:15c:2c4:203:63d6:5eb8:418d:c034"
       destinationAttributes: {
       }
       requestAttributes: {
       }
      }
      resourceName:  "projects/1004338142803"
      serviceName:  "storage.googleapis.com"
      status: {
       code:  7
       details: [
        0: {
         @type:  "type.googleapis.com/google.rpc.PreconditionFailure"
         violations: [
          0: {
           type:  "VPC_SERVICE_CONTROLS"
          }
         ]
        }
       ]
       message:  "Request is prohibited by organization's policy"
      }
     }
     receiveTimestamp:  "2018-11-30T16:34:46.948010626Z"
     resource: {
      labels: {
       method:  "google.storage.Write"
       project_id:  "corp-resources-private"
       service:  "storage.googleapis.com"
      }
      type:  "audited_resource"
     }
     severity:  "ERROR"
     timestamp:  "2018-11-30T16:34:46.898098978Z"
    }
    

この例の監査ログは、サービス境界を越えてデータをコピーできないことを示しています(両方のリソースが監査ログレコードに記録されています)。 リクエストが境界の外側(public-network の VM)から発生し、バケットの 1 つが境界(corp-resources-public-1)の外側に存在しています。

境界の外側から corp-resources-public-1 バケットへの書き込みはできるので、前の例で失敗したチェックはパスします。ただし、データを実際にコピーする際のチェックは失敗します。

この例でわかるように、ユーザーの 1 回の操作で複数の内部オペレーションが発生し、それぞれのオペレーションに VPC Service Controls のチェックが実行されます。

境界内の VM からの BigQuery データセットのコピー

この例では、プロジェクト 927005422713perimeter-network)の VM がプロジェクト corp-resources-private から corp-resources-public117961063178)に BigQuery データセットをコピーしようとしています。perimeter-networkcorp-resources-private は境界を共有し、corp-resources-public は境界の外側に存在します。

VM は次のコマンドを使用します。

bq cp corp-resources-private:babynames.yob2000 \
      corp-resources-public:babynames.yob2000
    

次の結果が返されます。

BigQuery error in cp operation: VPC Service Controls: Request is prohibited by
    organization's policy. Operation ID: c00dbc44-460f-4bd0-9d09-cda98ac800f9
    

次の監査ログレコードが生成されます。

{
     insertId:  "146o5fd2hbp"
     logName:  "projects/perimeter-network/logs/cloudaudit.googleapis.com%2Fpolicy"
     protoPayload: {
      @type:  "type.googleapis.com/google.cloud.audit.AuditLog"
      authenticationInfo: {
      }
      metadata: {
       @type:  "type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
       resourceNames: [
        0:  "projects/117961063178"
       ]
       violationReason:  "RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER"
      }
      methodName:  "bigquery.googleapis.com/bigquery.tables.get"
      requestMetadata: {
       callerIp:  "131.201.221.16"
       callerNetwork:  "//compute.googleapis.com/projects/perimeter-network/global/networks/__unknown__"
       destinationAttributes: {
       }
       requestAttributes: {
       }
      }
      resourceName:  "projects/927005422713"
      serviceName:  "bigquery.googleapis.com"
      status: {
       code:  7
       details: [
        0: {
         @type:  "type.googleapis.com/google.rpc.PreconditionFailure"
         violations: [
          0: {
           type:  "VPC_SERVICE_CONTROLS"
          }
         ]
        }
       ]
       message:  "Request is prohibited by organization's policy"
      }
     }
     receiveTimestamp:  "2018-11-28T00:27:05.688803777Z"
     resource: {
      labels: {
       method:  "bigquery.googleapis.com/bigquery.tables.get"
       project_id:  "perimeter-network"
       service:  "bigquery.googleapis.com"
      }
      type:  "audited_resource"
     }
     severity:  "ERROR"
     timestamp:  "2018-11-28T00:27:05.378584819Z"
    }
    

この例では、ロギング メカニズムと BigQuery の分散アーキテクチャの制限により、1 つの API アクションで、このリクエストで使用されているすべてのリソースを確認することはできません。

監査ログレコードを見ると、データをコピーする際に、BigQuery がプロジェクト perimeter-network(リクエストの送信元)のネットワークを使用してターゲット プロジェクト(corp-resources-public)にアクセスする必要があるため、オペレーションが失敗しています。corp-resources-public は、perimeter-network を保護する境界の外側にあります。リクエストは、corp-resources-public にデータを抽出する試みとして拒否されます。

この例でもわかるように、データのコピーのような 1 つのオペレーションが、Cloud Storage、BigQuery、Bigtable など、さまざまなストレージ システムのデータにアクセスする複数の処理を開始する可能性があります。オペレーションの実行方法によっては、生成される監査ログレコードが元のユーザー コマンドと異なることがあります。特に、1 つのサービス内で複数のチェックが実行され、失敗した場合は結果が異なります。

プロジェクトから Dataproc ジョブを読み込む

この例では、Dataproc などのデータ処理サービスの使用中に間接的に発生した VPC Service Controls のエラーをデバッグする方法を示します。

この例では、VPC Service Controls で保護されたプロジェクトで Dataproc クラスタが実行されています。Hello-world.py は、境界内の Cloud Storage バケットのデータにアクセスし、境界外の別のバケットに書き込む pyspark ジョブです。このオペレーションは、VPC Service Controls によってブロックされます。

Hello-world.py を実行するため、次のコマンドが使用されます。

gcloud dataproc jobs submit pyspark hello-world.py --cluster test-cluster-new2
    

次の結果が返されます。

Job [50f16ca8-5102-442b-a545-eed5e4f5f5da] submitted.
    Waiting for job output...
    18/11/29 00:31:34 INFO org.spark_project.jetty.util.log: Logging initialized @2552ms
    18/11/29 00:31:34 INFO org.spark_project.jetty.server.Server: jetty-9.3.z-SNAPSHOT
    18/11/29 00:31:34 INFO org.spark_project.jetty.server.Server: Started @2640ms
    18/11/29 00:31:34 INFO org.spark_project.jetty.server.AbstractConnector: Started ServerConnector@1f1c18ec{HTTP/1.1,[http/1.1]}{0.0.0.0:4040}
    18/11/29 00:31:34 INFO com.google.cloud.hadoop.fs.gcs.GoogleHadoopFileSystemBase: GHFS version: 1.6.4-hadoop2
    18/11/29 00:31:35 INFO org.apache.hadoop.yarn.client.RMProxy: Connecting to ResourceManager at test-cluster-new2-m/10.246.0.3:8032
    18/11/29 00:31:37 INFO org.apache.hadoop.yarn.client.api.impl.YarnClientImpl: Submitted application application_1522454176466_0005
    Traceback (most recent call last):
      File "/tmp/50f16ca8-5102-442b-a545-eed5e4f5f5da/hello-world.py", line 8, in <module>
        lear.saveAsTextFile("gs://corp-resources-public-1/out.txt")
      File "/usr/lib/spark/python/lib/pyspark.zip/pyspark/rdd.py", line 1553, in saveAsTextFile
      File "/usr/lib/spark/python/lib/py4j-0.10.4-src.zip/py4j/java_gateway.py", line 1133, in __call__
      File "/usr/lib/spark/python/lib/py4j-0.10.4-src.zip/py4j/protocol.py", line 319, in get_return_value
    py4j.protocol.Py4JJavaError: An error occurred while calling o49.saveAsTextFile.
    : java.io.IOException: Error accessing: bucket: corp-resources-public-1, object: out.txt
        at com.google.cloud.hadoop.gcsio.GoogleCloudStorageImpl.wrapException(GoogleCloudStorageImpl.java:1767)
    $sp(PairRDDFunctions.scala:961)

     (truncated)

    Caused by: com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
    {
      "code" : 403,
      "errors" : [ {
        "domain" : "global",
        "message" : "Request violates VPC Service Controls.",
        "reason" : "vpcServiceControls"
      } ],
      "message" : "Request violates VPC Service Controls."
    }
        at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:145)

     (truncated)

    18/11/29 00:31:43 INFO org.spark_project.jetty.server.AbstractConnector: Stopped Spark@1f1c18ec{HTTP/1.1,[http/1.1]}{0.0.0.0:4040}
    ERROR: (gcloud.dataproc.jobs.submit.pyspark) Job [50f16ca8-5102-442b-a545-eed5e4f5f5da] entered state [ERROR] while waiting for [DONE].
    

saveAsTextFile が呼び出されたときに発生する IO 例外に注意してください。 Cloud Storage は、403 エラーとメッセージ Request violates VPC Service Controls を返します。このエラーは、Cloud Storage 監査ログのオペレーションを確認する必要があることを示しています。

コマンドが実行された perimeter-network プロジェクトの監査ログには、saveAsTextFile オペレーションの監査ログレコードがあります。

{
     insertId:  "qdj1o9d1run"
     logName:  "projects/corp-resources-private/logs/cloudaudit.googleapis.com%2Fpolicy"
     protoPayload: {
      @type:  "type.googleapis.com/google.cloud.audit.AuditLog"
      authenticationInfo: {
       principalEmail:  "1004338142803-compute@example.gserviceaccount.com"
      }
      metadata: {
       @type:  "type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
       resourceNames: [
        0:  "projects/_/buckets/corp-resources-public-1/objects/out.txt"
       ]
       violationReason:  "RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER"
      }
      methodName:  "google.storage.BillingRequiredRead"
      requestMetadata: {
       callerIp:  "10.246.0.3"
       callerNetwork:  "//compute.googleapis.com/projects/corp-resources-private/global/networks/__unknown__"
       destinationAttributes: {
       }
       requestAttributes: {
       }
      }
      resourceName:  "projects/1004338142803"
      serviceName:  "storage.googleapis.com"
      status: {
       code:  7
       details: [
        0: {
         @type:  "type.googleapis.com/google.rpc.PreconditionFailure"
         violations: [
          0: {
           type:  "VPC_SERVICE_CONTROLS"
          }
         ]
        }
       ]
       message:  "Request is prohibited by organization's policy"
      }
     }
     receiveTimestamp:  "2018-11-29T00:31:43.666227930Z"
     resource: {
      labels: {
       method:  "google.storage.BillingRequiredRead"
       project_id:  "corp-resources-private"
       service:  "storage.googleapis.com"
      }
      type:  "audited_resource"
     }
     severity:  "ERROR"
     timestamp:  "2018-11-29T00:31:43.608250320Z"
    }
    

監査ログの制限により、実際のオペレーションが write であっても、Cloud Storage の methodNameRead と表示されます。監査ログレコードを見ると、プロジェクト corp-resources-private 内のネットワークがバケット corp-resources-public-1 のリソースのデータにアクセスを試みたため(この場合は書き込み)、オペレーションが失敗しています。Cloud Storage の監査ログに制限があるため、プロジェクト バケット corp-resources-public-1 の所属先がわかりません。

corp-resources-public-1 を含むプロジェクトを特定するには、次のコマンドを使用します。

gsutil --debug ls -L -b gs://corp-resources-public-1 2>&1 | grep projectNumber
    

次の結果が返されます。

projectNumber: u'117961063178'
    

117961063178 はプロジェクト corp-resources-public で、これは境界外にあります。 このエラーは予期した動作です。

制限付き VIP でサポートされていないサービス

VPC Service Controls の制限付き VIP でサポートされていない API にアクセスを試みると、404 エラーが発生します。たとえば、Cloud DNS は現在 VPC Service Controls でサポートされていないため、制限付き VIP を使用している場合は Cloud DNS API を使用できません。

たとえば、次のコマンドを使用したとします。

gcloud dns managed-zones list
    

次の結果が返されます。

ERROR: (gcloud.dns.managed-zones.list) Project [corp-resources-private] not found: <!DOCTYPE html>
    <html lang=en>
      <meta charset=utf-8>
      <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
      <title>Error 404 (Not Found)!!1</title>
      <style>
        *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){ #logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){ #logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
      </style>
      <a href=//www.google.com/><span id=logo aria-label=Google></span></a>
      <p><b>404.</b> <ins>That's an error.</ins>
      <p>The requested URL <code>/dns/v1/projects/corp-resources-private/managedZones</code> was not found on this server.  <ins>That's all we know.</ins>
    

VPC Service Controls でサポートされず、制限付き VIP で使用できないサービスの場合、このタイプのエラーは予想されるエラーです。このエラーが VPC Service Controls でサポートされているサービスで発生した場合は、サービスに関する既知の制限事項で、このサービスが既知の制限かどうか確認してください。それ以外の場合は、問題を報告する必要があります

境界外のプロジェクトへのログのエクスポート

この例では、ログのエクスポートが VPC Service Controls でブロックされています。 エクスポート先のプロジェクト corp-resources-public が VPC Service Controls の境界外にあり、境界内のプロジェクト perimeter-network にシンクが作成されます。

たとえば、次のコマンドを使用したとします。

gcloud logging sinks describe example-sink
    

次の結果が返されます。

destination: bigquery.googleapis.com/projects/corp-resources-public/datasets/logs
    filter: |-
      resource.type="audited_resource"
      resource.labels.service="bigquery.googleapis.com"
    name: example-sink
    outputVersionFormat: V2
    writerIdentity: serviceAccount:p927005422713-439672@gcp-sa-logging.iam.gserviceaccount.com

    

次の監査ログレコードが生成されます。

{
     insertId:  "e5i2i8cbqw"
     logName:  "projects/perimeter-network/logs/cloudaudit.googleapis.com%2Fpolicy"
     protoPayload: {
      @type:  "type.googleapis.com/google.cloud.audit.AuditLog"
      authenticationInfo: {
       principalEmail:  "p927005422713-439672@gcp-sa-logging.iam.gserviceaccount.com"
      }
      metadata: {
       @type:  "type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
       resourceNames: [
        0:  "corp-resources-public"
       ]
       violationReason:  "RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER"
      }
      methodName:  "google.cloud.bigquery.v2.TableDataService.InsertAll"
      requestMetadata: {
       callerIp:  "2002:a49:8c51::"
       destinationAttributes: {
       }
       requestAttributes: {
       }
      }
      resourceName:  "projects/927005422713"
      serviceName:  "bigquery.googleapis.com"
      status: {
       code:  7
       details: [
        0: {
         @type:  "type.googleapis.com/google.rpc.PreconditionFailure"
         violations: [
          0: {
           type:  "VPC_SERVICE_CONTROLS"
          }
         ]
        }
       ]
       message:  "Request is prohibited by organization's policy"
      }
     }
     receiveTimestamp:  "2018-11-29T17:32:19.287138882Z"
     resource: {
      labels: {
       method:  "google.cloud.bigquery.v2.TableDataService.InsertAll"
       project_id:  "perimeter-network"
       service:  "bigquery.googleapis.com"
      }
      type:  "audited_resource"
     }
     severity:  "ERROR"
     timestamp:  "2018-11-29T17:32:19.054662413Z"
    }
    

監査ログレコードは、Logging ではなく BigQuery に対して生成されます。これは、Logging が書き込むシンクサービスが BigQuery のためです。

corp-resources-public がプロジェクト perimeter-network を保護する境界の外側に存在するため、エクスポートが失敗します。

この例で示したように、GCP サービスが p927005422713-439672@gcp-sa-logging.iam.gserviceaccount.com のような GCP マネージド サービスの内部アカウントを使用して別のサービスを呼び出す場合、リクエストのネットワーク プロジェクト(この場合は perimeter-network)はその ID から派生します。ログ エクスポートのリソースも同じ ID で表されます。

これは Google Cloud で一般的なパターンで、サービス間のやり取りの多くで行われています。

Cloud Storage への BigQuery の抽出

この例では、失敗した BigQuery から Cloud Storage への抽出をデバッグする方法について説明します。

この例では、corp-resources-privateperimeter-network がサービス境界で保護されたプロジェクトです。corp-resources-public は境界外にあるプロジェクトです。

次のコマンドを使用したとします。

bq extract babynames.yob2000
    

次の結果が返されます。

gs://corp-resources-public-1/export.txt
    Waiting on bqjob_r47ee34109d02b41_000001676b27157c_1 ... (1s) Current status: DONE
    BigQuery error in extract operation: Error processing job 'corp-resources-private:bqjob_r47ee34109d02b41_000001676b27157c_1': Access
    Denied: BigQuery BigQuery: Permission denied while writing data.
    

このエラーは、VPC Service Controls に固有のものではありません。Cloud Identity やアクセス管理のエラーでも同様のエラーが発生します。

次の監査ログレコードが生成されます。

{
     insertId:  "4gbh6pe8jld7"
     logName:  "projects/corp-resources-private/logs/cloudaudit.googleapis.com%2Fdata_access"
     protoPayload: {
      @type:  "type.googleapis.com/google.cloud.audit.AuditLog"
      authenticationInfo: {
       principalEmail:  "storage-accessing@example.iam.gserviceaccount.com"
      }
      methodName:  "jobservice.jobcompleted"
      requestMetadata: {
       callerIp:  "10.5.0.4"
       callerNetwork:  "//compute.googleapis.com/projects/perimeter-network/global/networks/__unknown__"
       callerSuppliedUserAgent:  "google-api-python-client/1.6.5 (gzip),gzip(gfe)"
       destinationAttributes: {
       }
       requestAttributes: {
       }
      }
      resourceName:  "projects/corp-resources-private/jobs/bqjob_r47ee34109d02b41_000001676b27157c_1"
      serviceData: {
       @type:  "type.googleapis.com/google.cloud.bigquery.logging.v1.AuditData"
       jobCompletedEvent: {
        eventName:  "extract_job_completed"
        job: {
         jobConfiguration: {
          extract: {
           destinationUris: [
            0:  "gs://corp-resources-public-1/export.txt"
           ]
           sourceTable: {
            datasetId:  "babynames"
            projectId:  "corp-resources-private"
            tableId:  "yob2000"
           }
          }
         }
         jobName: {
          jobId:  "bqjob_r47ee34109d02b41_000001676b27157c_1"
          location:  "US"
          projectId:  "corp-resources-private"
         }
         jobStatistics: {
          createTime:  "2018-12-01T19:03:03.908Z"
          endTime:  "2018-12-01T19:03:05.494Z"
          startTime:  "2018-12-01T19:03:04.013Z"
         }
         jobStatus: {
          additionalErrors: [
           0: {
            code:  7
            message:  "Access Denied: BigQuery BigQuery: Permission denied while writing data."
           }
          ]
          error: {
           code:  7
           message:  "Access Denied: BigQuery BigQuery: Permission denied while writing data."
          }
          state:  "DONE"
         }
        }
       }
      }
      serviceName:  "bigquery.googleapis.com"
      status: {
       code:  7
       message:  "Access Denied: BigQuery BigQuery: Permission denied while writing data."
      }
     }
     receiveTimestamp:  "2018-12-01T19:03:05.532169998Z"
     resource: {
      labels: {
       project_id:  "corp-resources-private"
      }
      type:  "bigquery_resource"
     }
     severity:  "ERROR"
     timestamp:  "2018-12-01T19:03:05.503Z"
    }
    

この監査ログレコードで、storage-accessing@example.iam.gserviceaccount.com はオペレーションの実行を試みた ID です。ここでは、コマンドの実行に必要な Cloud IAM 権限が storage-accessing@example.iam.gserviceaccount.com にあるとします。

Cloud IAM 権限は原因ではないので、次に VPC Service Controls のエラーかどうかを確認します。

宛先のサービス(Cloud Storage)の監査ログレコードに、詳しい失敗理由が記録されています。

{
     insertId:  "1bq397kcfj1"
     logName:  "projects/corp-resources-private/logs/cloudaudit.googleapis.com%2Fpolicy"
     protoPayload: {
      @type:  "type.googleapis.com/google.cloud.audit.AuditLog"
      authenticationInfo: {
       principalEmail:  "storage-accessing@example.iam.gserviceaccount.com"
      }
      metadata: {
       @type:  "type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
       resourceNames: [
        0:  "projects/1004338142803"
        1:  "projects/_/buckets/corp-resources-public-1"
       ]
       violationReason:  "RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER"
      }
      methodName:  "google.storage.BillingRequiredRead"
      requestMetadata: {
       callerIp:  "10.5.0.4"
       callerNetwork:  "//compute.googleapis.com/projects/perimeter-network/global/networks/__unknown__"
       destinationAttributes: {
       }
       requestAttributes: {
       }
      }
      resourceName:  "projects/1004338142803"
      serviceName:  "storage.googleapis.com"
      status: {
       code:  7
       details: [
        0: {
         @type:  "type.googleapis.com/google.rpc.PreconditionFailure"
         violations: [
          0: {
           type:  "VPC_SERVICE_CONTROLS"
          }
         ]
        }
       ]
       message:  "Request is prohibited by organization's policy"
      }
     }
     receiveTimestamp:  "2018-12-01T19:03:05.617451586Z"
     resource: {
      labels: {
       method:  "google.storage.BillingRequiredRead"
       project_id:  "corp-resources-private"
       service:  "storage.googleapis.com"
      }
      type:  "audited_resource"
     }
     severity:  "ERROR"
     timestamp:  "2018-12-01T19:03:05.420005215Z"
    }
    

このログを見ると、コマンドを完了するために、2 つのプロジェクト 1004338142803corp-resources-private-1)と corp-resources-public が使用されていることがわかります。これらのプロジェクトは境界を共有していないため、抽出ジョブが失敗しています。

この例が示しているように、複雑なマルチサービス オペレーションの場合、元のサービスと宛先のサービスの両方の監査ログに、デバッグに役立つデータが記録されている可能性があります。