トラブルシューティング

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

VPC Service Controls のエラーを探す

このセクションでは、監査ログで VPC のエラーを見つける方法について説明します。

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

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

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

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

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

    Cloud Logging に移動

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

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

VPC Service Controls に関連するエラーを見つけるには、Cloud Logging を使用します。

Console

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

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

  1. Google Cloud コンソールで、サービス境界内のプロジェクトの [Cloud Logging] ページに移動します。

    Cloud 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>="START_DATETIME" AND
      timestamp<="END_DATETIME"'
    

    ここで

    • START_DATETIMEEND_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 つ以上のプロジェクトで、それらのプロジェクト内の任意のサービスに対するリクエストを行うことが可能になります。こうしたリクエストは、サービスが境界によって保護されていても許可されます。

  • リクエスト元のサービスと対象のリソースの両方が境界により保護されないようにする。このシナリオでは、サービスが保護されないためオペレーションは成功します。

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

VPC Service Controls は Google Cloud のプロパティを変更します。何を探せばよいのかわからない場合、サービス間でカスケード効果が生じる可能性があります。

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

サービス境界内のプロジェクトで、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.

上り(内向き)ルールと下り(外向き)ルールの違反

監査ログには、上り(内向き)ルールと下り(外向き)ルールの違反に関する情報が記録されます。この情報は境界違反の把握に役立ちます。

上り(内向き)ルール違反

上り(内向き)ルール違反は、境界外の API クライアントが境界内のリソースにアクセスしようとしたことを示します。一致する上り(内向き)ルールまたはアクセスレベルが存在しないため、サービス境界はリクエストを拒否します。

監査ログの上り(内向き)ルール違反には次の情報が含まれます。

  • 上り(内向き)ルール違反が発生した境界の名前。
  • 境界外部の API クライアントがアクセスを試みた境界内のリソース。

次の上り(内向き)ルール違反の例では、境界外の API クライアントが、境界 prod-perimeter 内の Cloud Storage バケット prod-protected-storage-bucket にアクセスを試みています。

ingressViolations: [
  0: {
    targetResource: "projects/1234/buckets/prod-protected-storage-bucket"
    servicePerimeter: "accessPolicies/123456789/servicePerimeters/prod-perimeter"
  }
]

下り(外向き)ルール違反

監査ログの下り(外向き)ルール違反は、次のいずれかのイベントを示します。

  • 境界内の API クライアントが境界外のリソースにアクセスを試みた。
  • API リクエストに境界内のリソースと境界外のリソースが含まれている。たとえば、境界内のバケットと境界外のバケットが指定されたコピーコマンドが Cloud Storage クライアントから実行されています。

一致する下り(外向き)ルールがないため、サービス境界はリクエストを拒否します。監査ログの下り(外向き)ルール違反には次の情報が含まれます。

  • ソースの種類(ネットワーク、リソースなど)。
  • 下り(外向き)違反が発生した境界のソース(リソースまたはネットワーク)。
  • 下り(外向き)違反が発生した境界。
  • リクエストがアクセスしようとした境界外のターゲット リソース。

次の下り(外向き)ルール違反の例では、API リクエストに境界 prod-perimeter 内の projects/5678 のリソースと、境界外にある Cloud Storage バケット external-storage-bucket のオブジェクトが含まれています。

egressViolations: [
  0: {
    sourceType: "Resource"
    source: "projects/5678"
    targetResource: "projects/4321/buckets/external-storage-bucket/objects/corp-resources.json"
    servicePerimeter: "accessPolicies/123456789/servicePerimeters/prod-perimeter"
  }
]

VPC Service Controls によってブロックされたリクエストのデバッグ

VPC Service Controls によってブロックされたリクエストを調査する場合、VPC Service Controls の監査ログが基本的なツールとなります。

アクセスが予期せずにブロックされた場合は、サービス境界で保護されているプロジェクトの監査ログを確認します。このログには、リクエストされたリソースやリクエストが拒否された理由に関する重要なデータが記録されています。監査ログについては、トラブルシューティングを使用して問題を診断するをご覧ください。

以降のセクションでは、VPC Service Controls の使用時に発生する可能性のある violationReason の値について説明します。

NETWORK_NOT_IN_SAME_SERVICE_PERIMETER

この問題の原因として次のいずれかが考えられます。

  • サービス境界内の VPC ネットワーク内のクライアントが、同じ境界にないプロジェクトへのアクセスを試みている。このリクエストによって下り(外向き)違反が発生します。この問題を解決するには、下り(外向き)ルールを作成します。
  • サービス境界外の VPC ネットワーク内のクライアントが、サービス境界で保護されているプロジェクトにアクセスしようとしている。このリクエストによって上り(内向き)違反が発生します。この問題を解決するには、上り(内向き)ルールを作成します。

クライアントは、Compute Engine や Google Kubernetes Engine の VM から、あるいは Cloud Interconnect や VPC ネットワークを使用して構成された VPN を介してオンプレミス ネットワークからリクエストを送信できます。

次の図は、サービス境界内の VPC ネットワークのクライアントが境界外のプロジェクトにアクセスしようとしたときに発生する下り(外向き)違反を示しています。

NETWORK_NOT_IN_SAME_SERVICE_PERIMETER による下り(外向き)違反。

下り(外向き)違反の例を次に示します。

egressViolations: [
{
  servicePerimeter: "accessPolicies/<POLICY_NAME>/servicePerimeters/<PERIMETER_NAME>"
  source: "projects/<NETWORK_PROJECT_NUMBER>"
  sourceType: "Network"
  targetResource: "projects/<RESOURCE_PROJECT_NUMBER>"
}
]

ここで

  • <POLICY_NAME> は、アクセス ポリシーの数値名です。
  • <PERIMETER_NAME> はサービス境界の名前です。
  • <NETWORK_PROJECT_NUMBER> は、VPC ネットワークを保持する Google Cloud プロジェクトのプロジェクト番号です。
  • <RESOURCE_PROJECT_NUMBER> は、リソースを含む Google Cloud プロジェクトのプロジェクト番号です。

次の図は、境界外のクライアントが境界内のプロジェクトにアクセスしようとしたときに発生する上り(内向き)違反を示しています。

NETWORK_NOT_IN_SAME_SERVICE_PERIMETER による上り(内向き)違反。

上り(内向き)違反の例を次に示します。

ingressViolations: [
{
          targetResource: "projects/<RESOURCE_PROJECT_NUMBER>",
      source: "projects/<NETWORK_PROJECT_NUMBER>"
          servicePerimeter: "accessPolicies/<POLICY_NAME>/servicePerimeters/<PERIMETER_NAME>"
}
]

ここで

  • <RESOURCE_PROJECT_NUMBER> は、リソースを含む Google Cloud プロジェクトのプロジェクト番号です。
  • <NETWORK_PROJECT_NUMBER> は、VPC ネットワークを保持する Google Cloud プロジェクトのプロジェクト番号です。
  • <POLICY_NAME> は、アクセス ポリシーの数値名です。
  • <PERIMETER_NAME> はサービス境界の名前です。

RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER

この問題は、1 つのリクエストが複数のリソースにアクセスしていて、リソースが同じサービス境界内にない場合に発生します。この問題は、クライアントが配置されている場所や、クライアントがリソースにアクセスできるかどうかにかかわらず発生します。この問題を解決するには、下り(外向き)ルールを作成します。

次の図は、クライアントが境界外のプロジェクトとサービス境界内のプロジェクトからリソースにアクセスする様子を示しています。

クライアントが境界外のプロジェクトからリソースにアクセスするために発生する下り(外向き)違反。

次の図では、クライアントが 2 つの異なるサービス境界にあるプロジェクトからリソースにアクセスし、境界が相互に通信していない様子を示します。

クライアントが 2 つの異なるサービス境界にあるプロジェクトからリソースにアクセスしたことによる下り(外向き)違反。

下り(外向き)違反の例を次に示します。

egressViolations: [
{
  servicePerimeter: "accessPolicies/<POLICY_NAME>/servicePerimeters/<PERIMETER_NAME>"
  source: "projects/<RESOURCE_PROJECT_INSIDE_THIS_PERIMETER>"
  sourceType: "Resource"
  targetResource: "projects/<RESOURCE_PROJECT_OUTSIDE_THIS-PERIMETER>"
}
]

ここで

  • <POLICY_NAME> は、アクセス ポリシーの数値名です。
  • <PERIMETER_NAME> はサービス境界の名前です。
  • <RESOURCE_PROJECT_INSIDE_THIS_PERIMETER> は、境界内にある Google Cloud プロジェクトのプロジェクト番号です。
  • <RESOURCE_PROJECT_OUTSIDE_THIS_PERIMETER> は、境界外の Google Cloud プロジェクトのプロジェクト番号です。

NO_MATCHING_ACCESS_LEVEL

この問題は、Google Cloud ネットワーク外のクライアントが、境界外から Google Cloud ネットワーク リソースにアクセスしようとした場合に発生します。この問題を解決するには、アクセスレベルではなく上り(内向き)ルールを作成することをおすすめします。これは、上り(内向き)ルールが詳細なアクセス制御を提供するためです。

次の図は、境界外からリソースにアクセスしようとしているクライアントを示しています。

NO_MATCHING_ACCESS_LEVEL による上り(内向き)違反。

上り(内向き)違反の例を次に示します。

authenticationInfo: {
  principalEmail: "EMAIL"
}
requestMetadata: {
callerIp: "<PUBLIC_IP_ADDRESS>"
deviceState: "Cross Organization"
}
ingressViolations: [
        {
          targetResource: "projects/<RESOURCE_PROJECT_NUMBER>",
          servicePerimeter: "accessPolicies/<POLICY_NAME>/servicePerimeters/<PERIMETER-NAME>"
        }
  ]

ここで

  • <EMAIL> は、サービス アカウントまたは認証されたユーザーのメールアドレスです。
  • <PUBLIC_IP_ADDRESS> は呼び出し元の IP アドレスです。インターネットからの呼び出しの場合は、パブリック IPv4 または IPv6 アドレスになります。
  • <RESOURCE_PROJECT_NUMBER> は、リソースを含む Google Cloud プロジェクトのプロジェクト番号です。
  • <POLICY_NAME> は、アクセス ポリシーの数値名です。
  • <PERIMETER_NAME> はサービス境界の名前です。

SERVICE_NOT_ALLOWED_FROM_VPC

この問題は、クライアントが VPC ネットワークから Google Cloud リソースにアクセスしようとした場合に発生します。クライアントは、Compute Engine や Google Kubernetes Engine の VM から、あるいは Cloud Interconnect や VPC ネットワークを使用して構成された VPN を介してオンプレミス ネットワークからリクエストを送信できます。

この問題を解決するには、サービス境界の VPC からアクセス可能なサービスの構成で、呼び出されているサービスが許可されていることを確認します。

サンプル事例

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

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

この例では、VPC Service Controls は従業員のワークステーション(callerIp)からプロジェクト corp-storage 内の Cloud Storage バケットへのリクエストをブロックします。

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

{
 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 が境界外のリソースです。

境界内の 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 が境界外のリソースです。

境界外の 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 など、さまざまなストレージ システムのデータにアクセスする複数の処理の引き金となる可能性があります。オペレーションの実行方法によっては、生成される監査ログレコードが元のユーザー コマンドとは異なる場合があります。また、特定のサービス内で複数のチェックが行われ、チェックに失敗すると、生成された監査ログレコードが元のユーザー コマンドと異なるように見えることもあります。

プロジェクトからの 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 エラーが発生します。たとえば、VPC Service Controls は Cloud DNS をサポートしません。制限付き 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 を保護する境界の外側に存在するため、エクスポートが失敗します。

この例で示すように、ある Google Cloud サービスが Google Cloud 内部のマネージド サービス アカウント(p927005422713-439672@gcp-sa-logging.iam.gserviceaccount.com など)を使用して別のサービスを呼び出す場合、リクエストの「ネットワーク プロジェクト」(この場合、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 に固有のエラーではありません。Identity and Access Management のエラーが発生した場合も、同様のエラーが表示されます。

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

{
 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 です。この例では、コマンドの実行に必要な IAM 権限が storage-accessing@example.iam.gserviceaccount.com にあるとします。

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 が使用されていることがわかります。これらのプロジェクトは境界を共有していないため、抽出ジョブが失敗しています。

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