Résoudre les problèmes courants

Cette page présente les problèmes que vous pouvez rencontrer lors de la configuration de VPC Service Controls.

Comportement inattendu d'une règle étendue

Vous remarquerez peut-être des cas de non-respect inattendus de VPC Service Controls que votre règle définie doit autoriser. Il s'agit d'un problème connu. Si vous ne disposez pas d'une règle d'accès au niveau de l'organisation, vous risquez de rencontrer des problèmes inattendus avec vos stratégies d'accès cloisonné.

Pour résoudre ce problème, créez une règle d'accès au niveau de l'organisation à l'aide de la commande suivante:

gcloud access-context-manager policies create --organization <var>ORGANIZATION_ID</var> --title <var>POLICY_TITLE</var>

Remplacez les éléments suivants :

  • ORGANIZATION_ID : ID de l'organisation.
  • POLICY_TITLE: titre lisible de votre règle d'accès.

Pour en savoir plus, consultez Créer une règle d'accès.

VPC partagé

Lorsque vous utilisez un VPC partagé, le périmètre de service incluant les projets appartenant à un réseau VPC partagé doit également inclure le projet qui héberge le réseau. Lorsque les projets appartenant à un réseau VPC partagé ne se trouvent pas dans le même périmètre que le projet hôte, les services peuvent ne pas fonctionner comme prévu ou être entièrement bloqués.

Vérifiez que l'hôte du réseau VPC partagé se trouve dans le même périmètre de service que les projets connectés au réseau.

Requêtes entre périmètres

Normalement, des niveaux d'accès sont utilisés pour autoriser les requêtes provenant de l'extérieur d'un périmètre de service pour des ressources protégées à l'intérieur d'un périmètre.

Cependant, une requête provenant d'un projet situé dans un périmètre et portant sur une ressource protégée dans un autre périmètre est refusée, même si le niveau d'accès autorise normalement la requête.

Supposons que le projet A du périmètre 1 envoie une requête pour une ressource du projet B. La ressource du projet B est protégée par le périmètre 2. La requête est refusée car le projet A se trouve dans un périmètre distinct, même si un niveau d'accès pour le périmètre 2 autorise normalement la requête pour la ressource protégée.

Utilisez l'une des approches suivantes pour faciliter les requêtes entre périmètres:

  • Utilisez une règle de sortie et une règle d'entrée. Pour autoriser les requêtes provenant d'un autre périmètre vers des ressources protégées de votre périmètre, l'autre périmètre doit utiliser une règle de sortie et vous devez définir une règle d'entrée dans votre périmètre.

  • Utiliser les liaisons de périmètre. Les liaisons permettent à au moins deux projets situés dans des périmètres différents d'envoyer des requêtes aux services de ces projets. Ces requêtes sont autorisées même si les services sont protégés par leurs périmètres respectifs.

  • Assurez-vous que les périmètres ne protègent pas le service demandeur et la ressource cible. L'opération va alors réussir, car les services ne sont pas protégés.

L'adresse e-mail est incorrecte ou inexistante

Lorsque vous mettez à jour un périmètre contenant un compte principal supprimé, le message d'erreur The email address is invalid or non-existent peut s'afficher.

Pour résoudre ce problème, vous pouvez effectuer l'une des tâches suivantes:

  • Supprimez l'adresse e-mail non valide du périmètre, y compris les niveaux d'accès et les règles d'entrée et de sortie.

    Vous pouvez utiliser la console Google Cloud ou la Google Cloud CLI.

  • Effectuez une opération groupée (Google Cloud CLI uniquement) si l'adresse e-mail se trouve à la fois dans la test à blanc et dans le périmètre forcé.

    1. Obtenez tous vos périmètres:
      gcloud access-context-manager perimeters list --format=list \
       --policy=<POLICY_NAME> > my-perimeters.yaml
    
    1. Supprimez l'adresse e-mail non valide du fichier my-perimeters.yaml et enregistrez-la sous le nom my-perimeters-updated.yaml.

    2. Remplacez tous vos périmètres:

      gcloud access-context-manager perimeters replace-all --format=list \
        --source-file=my-perimeters-updated.yaml \
        --policy=<POLICY_NAME>
    

Violations des règles d'entrée et de sortie

Le journal d'audit contient des informations sur les violations des règles d'entrée et de sortie qui vous aident à comprendre les violations de périmètre.

Violations des règles d'entrée

Une violation de règle d'entrée indique qu'un client API situé en dehors du périmètre a tenté d'accéder à une ressource située à l'intérieur du périmètre. Le périmètre de service rejette la requête, car il n'existe aucune règle d'entrée ni aucun niveau d'accès correspondant.

Une violation de règle d'entrée dans le journal d'audit contient les détails suivants :

  • Le nom du périmètre dans lequel la violation de la règle d'entrée s'est produite.
  • La ressource au sein du périmètre à laquelle le client API en dehors du périmètre a tenté d'accéder.

Dans l'exemple de violation de règle d'entrée suivant, un client API en dehors du périmètre tente d'accéder au bucket Cloud Storage prod-protected-storage-bucket situé au sein du périmètre prod-perimeter.

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

Violation des règles de sortie

Une violation de règle de sortie dans le journal d'audit indique l'un des événements suivants :

  • Un client API au sein du périmètre a tenté d'accéder à une ressource située en dehors du périmètre.
  • Une requête API implique une ressource située à l'intérieur du périmètre et une ressource en dehors du périmètre. Par exemple, un client Cloud Storage appelle une commande de copie, où un bucket se trouve dans le périmètre et l'autre en dehors du périmètre.

Le périmètre de service rejette la requête, car il n'existe aucune règle de sortie correspondante. Une violation de règle de sortie dans le journal d'audit inclut les éléments suivants :

  • Le type de source, tel que le réseau ou la ressource.
  • La source, qui est une ressource ou un réseau, pour laquelle le périmètre a rencontré une violation de sortie.
  • Le périmètre qui a rencontré une violation de sortie.
  • La ressource cible située en dehors du périmètre auquel la requête a tenté d'accéder.

Dans l'exemple de violation de règle de sortie suivant, la requête API inclut une ressource de projets/5678, qui se trouve dans le périmètre prod-perimeter, et un objet du bucket Cloud Storage external-storage-bucket, qui se trouve en dehors du périmètre.

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

Requêtes de débogage bloquées par VPC Service Controls

Le journal d'audit de VPC Service Controls est le principal outil de débogage permettant d'identifier la raison pour laquelle une requête a été bloquée par VPC Service Controls.

En cas de blocage inattendu de l'accès, consultez les journaux d'audit du projet protégé par le périmètre de service. Ces journaux contiennent des données importantes sur les ressources demandées et le motif du refus. Pour plus d'informations sur les journaux d'audit, consultez la section Diagnostiquer les problèmes à l'aide de l'outil de dépannage.

Les sections suivantes répertorient les valeurs violationReason que vous pouvez rencontrer lors de l'utilisation de VPC Service Controls.

NETWORK_NOT_IN_SAME_SERVICE_PERIMETER

Ce problème peut être dû à l'une des raisons suivantes:

  • Un client d'un réseau VPC situé dans un périmètre de service tente d'accéder à un projet qui n'est pas dans le même périmètre. Cette requête entraîne un cas de non-respect du trafic de sortie. Créez une règle de sortie pour résoudre ce problème.
  • Un client d'un réseau VPC situé en dehors d'un périmètre de service tente d'accéder à un projet protégé par le périmètre de service. Cette requête entraîne un non-respect des règles d'entrée. Créez une règle d'entrée pour résoudre ce problème.

Le client peut envoyer la requête à partir d'une VM Compute Engine ou Google Kubernetes Engine, ou à partir d'un réseau sur site via Cloud Interconnect ou d'un VPN configuré à l'aide d'un réseau VPC.

Le schéma suivant montre qu'une violation de sortie se produit lorsqu'un client d'un réseau VPC situé dans un périmètre de service tente d'accéder à un projet en dehors du périmètre:

Un cas de non-respect du trafic de sortie causé par NETWORK_NOT_IN_SAME_SERVICE_PERIMETER.

Voici un exemple de non-respect des règles de sortie:

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

Où :

  • <POLICY_NAME> est le nom numérique de votre règle d'accès.
  • <PERIMETER_NAME> est le nom du périmètre de service.
  • <NETWORK_PROJECT_NUMBER> est le numéro du projet Google Cloud qui contient votre réseau VPC.
  • <RESOURCE_PROJECT_NUMBER> est le numéro du projet Google Cloud qui contient la ressource.

Le schéma suivant montre qu'un cas de non-respect des règles d'entrée se produit lorsqu'un client situé en dehors du périmètre tente d'accéder à un projet situé à l'intérieur du périmètre:

Cas de non-respect des règles d'entrée dû à NETWORK_NOT_IN_SAME_SERVICE_PERIMETER.

Voici un exemple de non-respect des règles d'entrée:

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

Où :

  • <RESOURCE_PROJECT_NUMBER> est le numéro du projet Google Cloud qui contient la ressource.
  • <NETWORK_PROJECT_NUMBER> est le numéro du projet Google Cloud qui contient votre réseau VPC.
  • <POLICY_NAME> est le nom numérique de votre règle d'accès.
  • <PERIMETER_NAME> est le nom du périmètre de service.

Solution

Pour résoudre cette erreur, créez une règle d'entrée ou de sortie pour votre périmètre.

RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER

Ce problème se produit lorsqu'une même requête accède à plusieurs ressources, mais que celles-ci ne se trouvent pas dans le même périmètre de service. Ce problème se produit indépendamment de l'emplacement du client et de son accès aux ressources.

Le schéma suivant montre un client accédant à des ressources à partir d'un projet situé en dehors du périmètre et d'un projet situé dans le périmètre de service:

Un cas de non-respect du trafic de sortie dû à l'accès d'un client à des ressources depuis un projet situé en dehors du périmètre.

Le schéma suivant montre un client accédant à des ressources à partir de projets situés dans deux périmètres de service différents, mais que ces périmètres ne communiquent pas entre eux:

Violation de sortie due au fait qu'un client accède aux ressources de projets situés dans deux périmètres de service différents.

Voici un exemple de non-respect des règles de sortie:

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

Où :

  • <POLICY_NAME> est le nom numérique de votre règle d'accès.
  • <PERIMETER_NAME> est le nom du périmètre de service.
  • <RESOURCE_PROJECT_INSIDE_THIS_PERIMETER> est le numéro du projet Google Cloud situé dans le périmètre.
  • <RESOURCE_PROJECT_OUTSIDE_THIS_PERIMETER> est le numéro du projet Google Cloud situé en dehors du périmètre.

Solution

Pour résoudre ce problème, créez une règle de sortie pour votre périmètre.

NO_MATCHING_ACCESS_LEVEL

Ce problème se produit lorsque l'adresse IP, l'exigence de l'appareil ou l'identité de l'utilisateur ne correspond à aucune règle d'entrée ni aucun niveau d'accès attribué au périmètre. Cela signifie qu'un client qui ne fait pas partie du réseau Google Cloud tente d'accéder aux ressources réseau Google Cloud depuis l'extérieur du périmètre. Par exemple, l'adresse IP correspondant au champ callerIp de l'enregistrement d'audit ne correspond à aucune plage CIDR définie dans les niveaux d'accès du périmètre de service.

Si l'adresse IP de l'appelant est manquante ou apparaît en tant qu'adresse IP interne, cette violation peut être due à un service Google Cloud qui n'est pas intégré à VPC Service Controls. Cela peut être dû au fait que le service Google Cloud tente d'accéder à un service protégé et échoue, comme prévu.

Pour résoudre ce problème, nous vous recommandons de créer une règle d'entrée plutôt qu'un niveau d'accès, car une règle d'entrée fournit un contrôle d'accès précis.

Le schéma suivant montre un client essayant d'accéder à des ressources depuis l'extérieur du périmètre:

Cas de non-respect des règles d'entrée dû à NO_MATCHING_ACCESS_LEVEL.

Voici un exemple de non-respect des règles d'entrée:

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

Où :

  • <EMAIL> est l'adresse e-mail du compte de service ou de l'utilisateur authentifié.

    Si vous utilisez un service Google Cloud non compatible avec VPC Service Controls, les adresses e-mail appartenant au domaine google.com sont masquées et remplacées par google-internal. google-internal fait référence aux identités internes appartenant à Google.

  • <PUBLIC_IP_ADDRESS> est l'adresse IP de l'appelant. Pour un appelant depuis Internet, il s'agit de l'adresse IPv4 ou IPv6 publique.

  • <RESOURCE_PROJECT_NUMBER> est le numéro du projet Google Cloud qui contient la ressource.

  • <POLICY_NAME> est le nom numérique de votre règle d'accès.

  • <PERIMETER_NAME> est le nom du périmètre de service.

Notez que dans ce cas, metadata.accessLevels peut toujours être présent, car ces niveaux d'accès peuvent ne pas être spécifiés dans le périmètre enfreint.

SERVICE_NOT_ALLOWED_FROM_VPC

Ce problème se produit lorsqu'un client tente d'accéder aux ressources Google Cloud à partir d'un réseau VPC. Le client peut envoyer la requête à partir d'une VM Compute Engine ou Google Kubernetes Engine, ou à partir d'un réseau sur site via Cloud Interconnect ou d'un VPN configuré à l'aide d'un réseau VPC.

Pour résoudre ce problème, assurez-vous que le service appelé est autorisé par la configuration Services accessibles par VPC du périmètre de service.

Exemples de scénarios

Les exemples suivants couvrent des problèmes que vous pouvez rencontrer lors de l'utilisation de VPC Service Controls :

Accès à Cloud Storage à partir d'un environnement sur site

Dans cet exemple, VPC Service Controls bloque une requête provenant du poste de travail d'un employé (identifié par callerIp) vers un bucket Cloud Storage dans le projet corp-storage.

La requête génère l'enregistrement de journal d'audit suivant :

{
 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"
}

Le projet corp-storage est inclus dans un périmètre de service. Le poste de travail de l'employé n'appartient à aucun réseau de ce périmètre. Comme le poste de travail de l'employé existe en dehors du périmètre, la requête est bloquée.

Accès à BigQuery à partir d'une VM située en dehors du projet

Dans cet exemple, une VM appartenant au projet 458854174376 (data-collector) tente d'exécuter une requête BigQuery sur un ensemble de données du projet 798816221974 (corp-resources-protected) ; cette requête est refusée.

La VM utilise la requête suivante :

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

La requête renvoie le résultat suivant :

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

L'enregistrement de journal d'audit suivant est généré :

{
 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"
}

Dans cet exemple, violationReason est NETWORK_NOT_IN_SAME_SERVICE_PERIMETER. callerNetwork est inclus en plus de callerIp. L'adresse IP est privée et le réseau est spécifié afin de lever toute ambiguïté. Les ressources pertinentes en cause ici sont répertoriées à deux emplacements : VpcServiceControlAuditMetadata.resourceNames et requestMetadata.callerNetwork (le projet qui héberge le réseau).

Le problème se produit car le projet corp-resources-protected se trouve dans un périmètre de service, tandis que data-collector, le projet qui inclut le réseau auquel la VM appartient, n'en fait pas partie. Dans ce cas, l'accès est logiquement refusé.

Requête BigQuery entre projets

Dans cet exemple, une VM appartenant au projet perimeter-network tente d'interroger les instances BigQuery de deux projets différents : corp-resources-protected, qui se trouve dans le même périmètre de service que perimeter-network, et corp-resources-public, qui se trouve lui en dehors.

La VM utilise la commande suivante :

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'

La requête renvoie le résultat suivant :

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

L'enregistrement de journal d'audit suivant est généré :

{
 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"
}

En examinant callerNetwork et VpcServiceControlAuditMetadata.resourceNames, nous pouvons voir trois projets : perimeter-network, 117961063178 (corp-resources-public) et 690885588241 (corp-resources-protected). Rappelez-vous que corp-resources-public ne se situe pas dans le même périmètre de service que perimeter-network et corp-resources-protected.

L'enregistrement violationReason, RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER indique que certaines ressources de la requête se situent en dehors du périmètre s'appliquant à la requête. Dans le cas présent, il s'agit de la ressource corp-resources-public.

Déplacer un fichier Cloud Storage dans le périmètre

Dans cet exemple, une VM du projet perimeter-network utilise une commande pour déplacer un fichier d'un bucket Cloud Storage, situé dans le projet corp-resources-protected, vers un autre bucket, situé dans le projet corp-resources-public.

La VM utilise la commande suivante :

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

La commande renvoie le résultat suivant :

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

L'enregistrement de journal d'audit suivant est généré :

{
 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"
}

Dans ce cas, le journal est moins explicite, car la méthode indiquée est BillingRequiredRead et l'action effectuée est move. Il s'agit d'une limitation associée au journal d'audit actuel de VPC Service Controls.

Bien que le motif soit moins évident, l'enregistrement de journal d'audit nous informe qu'une ressource de la requête se situe en dehors d'un périmètre s'appliquant à la requête. Dans ce cas, cette ressource est corp-resources-public.

Déplacer un fichier Cloud Storage en dehors du périmètre

Dans cet exemple, une VM du projet public-network utilise une commande pour déplacer un fichier d'un bucket Cloud Storage, situé dans le projet corp-resources-protected, vers un autre bucket, situé dans le projet corp-resources-public.

Le projet corp-resources-protected est protégé par un périmètre de service. Les projets public-network et corp-resources-public existent en dehors du périmètre.

La VM utilise la commande suivante :

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

La commande renvoie le résultat suivant :

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

L'enregistrement de journal d'audit suivant est généré :

{
 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"
}

Dans cet exemple, le journal d'audit indique qu'il n'est pas possible de copier des données au-delà de la limite du périmètre d'un service (les deux ressources figurent dans l'enregistrement de journal d'audit). Rappelez-vous que la requête provient de l'extérieur du périmètre (la VM du projet public-network) et que l'un des buckets se situe en dehors du périmètre (corp-resources-public-1).

Il est possible d'écrire des données dans le bucket corp-resources-public-1 depuis l'extérieur du périmètre, et de faire ainsi aboutir la vérification qui a échoué dans l'exemple précédent. Toutefois, la vérification ultérieure concernant la copie effective des données va échouer.

Cet exemple montre comment une opération utilisateur unique peut parfois entraîner plusieurs opérations internes qui doivent être autorisées par VPC Service Controls pour être appliquées.

Copie d'un ensemble de données BigQuery à partir d'une VM située dans le périmètre

Dans cet exemple, une VM du projet 927005422713 (perimeter-network) tente de copier un ensemble de données BigQuery du projet corp-resources-private vers le projet corp-resources-public (117961063178). Les projets perimeter-network et corp-resources-private partagent un même périmètre, tandis que corp-resources-public se situe en dehors de ce périmètre.

La VM utilise la commande suivante :

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

La commande renvoie le résultat suivant :

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

L'enregistrement de journal d'audit suivant est généré :

{
 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"
}

Dans cet exemple, aucune action d'API sous-jacente unique ne montre toutes les ressources en jeu dans cette requête, en raison des limites du mécanisme de journalisation et de l'architecture distribuée de BigQuery.

L'enregistrement du journal d'audit indique que l'opération a échoué car, pour pouvoir copier les données, BigQuery doit accéder au projet cible (corp-resources-public) en utilisant le réseau du projet perimeter-network (source de la requête). Rappelez-vous que le projet corp-resources-public est situé en dehors du périmètre qui protège perimeter-network. La requête est refusée, car elle est considérée comme une tentative d'exfiltration de données vers corp-resources-public.

Cet exemple illustre le fait qu'une opération conceptuelle, telle que la copie de données, peut déclencher diverses tentatives d'accès aux données de différents systèmes de stockage, comme Cloud Storage, BigQuery ou Bigtable. Selon le mode d'exécution de l'opération, l'enregistrement de journal d'audit généré diffère de la commande utilisateur d'origine. De plus, lorsque plusieurs vérifications sont effectuées au sein d'un service donné et échouent potentiellement, l'enregistrement de journal d'audit généré semble différent de la commande utilisateur d'origine.

Lecture d'une tâche Dataproc à partir d'un projet

Cet exemple montre comment déboguer des erreurs indirectes liées à VPC Service Controls lors de l'utilisation de services de traitement de données tels que Dataproc.

Dans cet exemple, un cluster Dataproc est exécuté dans un projet protégé par VPC Service Controls. Hello-world.py est une tâche pyspark qui tente d'accéder aux données d'un bucket Cloud Storage situé à l'intérieur du périmètre, puis de les écrire dans un autre bucket situé en dehors du périmètre. VPC Service Controls bloque l'opération qui écrit des données dans un bucket situé en dehors du périmètre.

La commande suivante est utilisée pour exécuter Hello-world.py :

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

La commande renvoie le résultat suivant :

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].

Notez l'exception d'E/S qui se produit lors de l'appel de la méthode saveAsTextFile. Cloud Storage renvoie une erreur 403 avec le message Request violates VPC Service Controls. L'erreur indique que l'opération du journal d'audit Cloud Storage doit être examinée.

Dans les journaux d'audit du projet perimeter-network, où la commande a été exécutée, il existe un enregistrement de journal d'audit pour l'opération 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"
}

En raison des limites du journal d'audit, le nom de la méthode (methodName) pour Cloud Storage est défini sur Read alors qu'il s'agit d'une opération write. L'enregistrement du journal d'audit indique que l'opération a échoué, car un réseau du projet corp-resources-private tentait d'accéder aux données (ici, en écriture) d'une ressource dans le bucket corp-resources-public-1. En raison des limites du journal d'audit de Cloud Storage, il n'est pas possible de savoir à quel projet appartient le bucket corp-resources-public-1.

Pour identifier le projet qui contient corp-resources-public-1, utilisez la commande suivante :

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

La commande renvoie le résultat suivant :

projectNumber: u'117961063178'

117961063178 est le projet corp-resources-public, qui se situe en dehors du périmètre. L'erreur est donc une conséquence normale.

Erreur due à des services non compatibles

Certains services Google Cloud dépendent d'autres services Google Cloud pour leur mise en œuvre. Si un service non compatible tel qu'App Engine est utilisé dans un projet protégé par un périmètre, les ressources du service risquent de ne pas être accessibles.

Pour en savoir plus sur les cas problématiques connus, consultez la section Limites connues concernant les services.

Service incompatible avec l'adresse IP virtuelle restreinte

Toute tentative d'accès à une API incompatible avec l'adresse IP virtuelle restreinte de VPC Service Controls génère une erreur 403. Par exemple, VPC Service Controls n'étant pas compatible avec App Engine, l'API App Engine Admin n'est pas disponible lorsque vous utilisez l'adresse IP virtuelle restreinte.

Par exemple, supposons que la commande suivante permet de répertorier tous les services App Engine dans un périmètre de service:

gcloud app services list

La commande renvoie le résultat suivant :

ERROR: (gcloud.app.services.list) User [***] does not have permission to access apps instance [***] (or it may not exist): <!DOCTYPE html>
<html lang=en>
  <meta charset=utf-8>
  <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
  <title>Error 403 (Forbidden)!!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>403.</b> <ins>That's an error.</ins>
  <p>Your client does not have permission to get URL <code>/v1/apps/***/services</code> from this server.  <ins>That's all we know.</ins>

Ce type d'erreur est attendu pour les services non compatibles avec VPC Service Controls et qui ne sont pas disponibles sur l'adresse IP virtuelle restreinte. Si cette erreur se produit pour un service compatible avec VPC Service Controls, nous vous recommandons de vérifier les limites connues pour ce service afin de déterminer s'il s'agit d'une limite connue. Sinon, vous devez signaler le problème.

Exportation de journal vers un projet situé en dehors du périmètre

Dans cet exemple, une exportation de journal est bloquée par VPC Service Controls. La destination de l'exportation (le projet corp-resources-public) se trouve en dehors du périmètre de VPC Service Controls, tandis que le récepteur est créé sur le projet perimeter-network, qui se situe dans le périmètre.

Supposons par exemple que la commande suivante soit utilisée :

gcloud logging sinks describe example-sink

La commande renvoie le résultat suivant :

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

L'enregistrement de journal d'audit suivant est généré :

{
 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"
}

L'enregistrement de journal d'audit est généré pour BigQuery, et non pour Logging. En effet, BigQuery est le service du récepteur sur lequel Logging tente d'écrire des données.

L'exportation échoue, car corp-resources-public se situe en dehors du périmètre qui protège perimeter-network.

Cet exemple montre que, dans les cas où un service Google Cloud appelle un autre service à l'aide d'un compte de service géré interne à Google Cloud, tel que p927005422713-439672@gcp-sa-logging.iam.gserviceaccount.com, le "projet réseau" (dans ce cas, perimeter-network) de la requête est dérivé de cette identité. Cette même identité représente la ressource d'exportation de journal elle-même.

Cette tendance est courante dans Google Cloud et s'applique à de nombreux cas d'interaction entre les services.

Extraction BigQuery vers Cloud Storage

Cet exemple explique comment déboguer les échecs d'extraction BigQuery vers Cloud Storage.

Ici, corp-resources-private et perimeter-network sont des projets protégés par un périmètre de service. corp-resources-public est un projet qui se situe en dehors du périmètre.

Supposons que la commande suivante ait été utilisée :

bq extract babynames.yob2000

La commande renvoie le résultat suivant :

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.

Dans ce cas, l'erreur n'implique pas spécifiquement VPC Service Controls. Une erreur similaire s'affiche en cas d'échec de Cloud IAM.

L'enregistrement de journal d'audit suivant est généré :

{
 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"
}

Dans cet enregistrement de journal d'audit, storage-accessing@example.iam.gserviceaccount.com est considéré comme l'identité qui tente d'exécuter l'opération. Dans cet exemple, supposons que storage-accessing@example.iam.gserviceaccount.com dispose des autorisations IAM requises pour exécuter la commande.

Comme les autorisations IAM ne sont pas en cause, l'étape suivante consiste à rechercher les échecs liés à VPC Service Controls.

L'enregistrement de journal d'audit pour le service de destination (Cloud Storage) contient les raisons détaillées de l'échec :

{
 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"
}

Ce journal indique clairement que les deux projets 1004338142803 (corp-resources-private-1) et corp-resources-public sont tous deux utilisés pour exécuter la commande. Comme ils ne partagent pas de périmètre, la tâche d'extraction échoue.

Cet exemple montre que lorsque vous avez affaire à des opérations multiservices complexes, les journaux d'audit des services sources et de destination peuvent contenir des données de débogage utiles.

Étapes suivantes