Soluciona problemas

En esta página, se enumeran varios problemas que pueden surgir cuando se intentan configurar los Controles del servicio de VPC.

Detecta errores en los Controles del servicio de VPC

En esta sección, se describen dos métodos para detectar errores de VPC en los registros de auditoría: usar el ID único de un error o los metadatos a fin de identificar errores.

Usa el ID único del error

Los errores que generan los Controles del servicio de VPC incluyen un ID único que se usa para identificar los registros de auditoría relevantes.

En este procedimiento, se usan términos de la documentación de Logging. Para obtener más información, consulta Filtros de registro básicos.

Para obtener información acerca de un error mediante el ID único, sigue estos pasos:

  1. En Cloud Console, ve a la página Stackdriver Logging del proyecto dentro del perímetro de servicio que activó ese error.

    Ir a la página de Stackdriver Logging

  2. En el cuadro de filtros de búsqueda, ingresa el ID único del error.

Filtra registros mediante metadatos

Para detectar errores relacionados con los Controles del servicio de VPC, usa Cloud Logging.

Console

En este procedimiento, se usan términos de la documentación de Logging. Para obtener más información, consulta Filtros de registro básicos.

Para obtener las últimas 24 horas de errores de los Controles del servicio de VPC en Logging, haz lo siguiente:

  1. En Google Cloud Console, ve a la página Stackdriver Logging del proyecto dentro del perímetro de servicio.

    Ir a la página de Stackdriver Logging

  2. En el cuadro de filtros de búsqueda, ingresa lo siguiente:

    protoPayload.metadata.@type:"type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
    
  3. En el menú de selección básico de recursos, selecciona Recurso auditado.

  4. En el menú desplegable de selección de rango de tiempo, selecciona Últimas 24 horas.

  5. De forma opcional, si deseas buscar los errores de los Controles del servicio de VPC que se produjeron durante un período diferente, usa el menú desplegable de selección de rango de tiempo para cambiar el rango.

gcloud

Para obtener las últimas 24 horas de errores de los Controles del servicio de VPC, usa el siguiente comando:

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

De forma predeterminada, el comando read está limitado a las últimas 24 horas. Para obtener los registros de los Controles del servicio de VPC durante un período diferente, usa uno de los siguientes comandos.

Para limitar los registros relacionados con la fecha actual, ejecuta lo siguiente:

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

En el ejemplo anterior, se ilustra lo siguiente:

Por ejemplo, para obtener todos los errores de los Controles del servicio de VPC que se produjeron durante la última semana, ejecuta lo siguiente:

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

Para limitar los registros a un período específico, ejecuta el siguiente comando:

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

En el ejemplo anterior, se ilustra lo siguiente:

Por ejemplo, para obtener todos los errores de los Controles del servicio de VPC que se produjeron entre el 22 y el 26 de marzo de 2019, ejecuta lo siguiente:

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"'

Servicios no compatibles

Para obtener más información sobre los productos y servicios compatibles con los Controles del servicio de VPC, consulta la página Productos compatibles.

Intentar restringir un servicio no compatible mediante la herramienta de línea de comandos de gcloud o la API de Access Context Manager generará un error.

Los Controles del servicio de VPC bloquearán el acceso entre proyectos de los servicios compatibles. Además, la VIP restringida se puede usar para bloquear la capacidad de las cargas de trabajo de llamar a servicios no compatibles.

VPC compartida

Cuando usas una VPC compartida, un perímetro de servicio que incluye proyectos que pertenecen a una red de VPC compartida también debe incluir el proyecto que aloja la red. Cuando los proyectos que pertenecen a una red de VPC compartida no están en el mismo perímetro que el proyecto host, es posible que los servicios no funcionen como se espera o que se bloqueen por completo.

Asegúrate de que el host de la red de VPC compartida esté en el mismo perímetro de servicio que los proyectos conectados a la red.

Solicitudes entre perímetros

Por lo general, los niveles de acceso se usan con el fin de permitir las solicitudes por fuera de un perímetro de servicio para recursos protegidos dentro de un perímetro.

Sin embargo, se rechazarán las solicitudes de un proyecto que esté en el perímetro de un recurso protegido en otro perímetro, incluso si un nivel de acceso permitiría la solicitud con normalidad.

Por ejemplo, supongamos que el Proyecto A en el Perímetro 1 solicita un recurso del Proyecto B. El recurso en el Proyecto B está protegido por el Perímetro 2. Dado que el Proyecto A está en un perímetro, incluso si un nivel de acceso para el Perímetro 2 permitiría la solicitud del recurso protegido con normalidad, la solicitud se rechaza.

Existen dos maneras de facilitar las solicitudes entre perímetros:

  • Usar puentes perimetrales. Los puentes permiten dos o más proyectos en diferentes perímetros para realizar solicitudes a cualquier servicio en esos proyectos. Estas solicitudes se permiten incluso si los perímetros están protegidos por los perímetros.

  • Asegúrate de que los perímetros no protejan al servicio de solicitud ni al recurso de destino. En esta situación, la operación tendrá éxito porque no hay servicios protegidos.

Determina si hay un error debido a los Controles del servicio de VPC

Debido a que los Controles del servicio de VPC modifican ciertas propiedades de bajo nivel de Google Cloud, pueden tener efectos en cascada en todos los servicios que pueden ser difíciles de depurar si no sabes qué buscar.

Para identificar si el error está relacionado con los Controles del servicio de VPC, verifica si habilitaste los Controles del servicio de VPC y si lo aplicaste a los proyectos y servicios que intentas usar. Esto se puede hacer a través de la herramienta de línea de comandos de gcloud o Cloud Console.

Si usas un servicio (quizás indirectamente, mediante otro servicio) que los Controles del servicio de VPC marcan como servicio restringido en un proyecto que se encuentra dentro de un perímetro de servicio, los Controles del servicio de VPC pueden fallar.

Para obtener información sobre casos problemáticos conocidos, consulta Limitaciones de servicios conocidas.

Por lo general, los servicios propagarán mensajes de error de sus dependencias. Si encuentras uno de los siguientes errores, es un problema de los Controles del servicio de VPC.

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

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

  • Otros servicios: 403: Request is prohibited by organization's policy.

Depura una solicitud bloqueada por razones inesperadas mediante los Controles del servicio de VPC

El registro de auditoría de los Controles del servicio de VPC es la herramienta principal para depurar por qué los Controles del servicio de VPC bloquearon una solicitud.

En la mayoría de los casos, cuando el acceso se bloquea de manera inesperada, consulta los registros de auditoría del proyecto que eran la fuente de la solicitud. Estos registros contienen datos importantes sobre los recursos solicitados y el motivo del rechazo de la solicitud.

Para obtener más información sobre cómo ver registros, lee Visualiza registros.

En la siguiente tabla, se enumeran los valores violationReason que puedes encontrar cuando usas los Controles del servicio de VPC.

violationReason Explicación
RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER Los recursos enumerados en resourceNames en el registro de auditoría no están en el mismo perímetro de servicio.
NETWORK_NOT_IN_SAME_SERVICE_PERIMETER Los recursos correspondientes a callerNetwork y resourceNames en el registro de auditoría no están en el mismo perímetro de servicio.
NO_MATCHING_ACCESS_LEVEL

La dirección IP correspondiente a callerIp en el registro de auditoría no coincide con ningún rango de IP en los niveles de acceso asignados al perímetro de servicio.

Situaciones de ejemplo

Los siguientes ejemplos abarcan situaciones que puedes encontrarte cuando usas los Controles del servicio de VPC.

Acceso a Cloud Storage desde las instalaciones locales

En este ejemplo, los Controles del servicio de VPC bloquean una solicitud de una estación de trabajo de empleado (identificada por callerIp) a un depósito de Cloud Storage en el proyecto corp-storage.

La solicitud genera el siguiente registro de auditoría:

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

El proyecto corp-storage se incluye en un perímetro de servicio. La estación de trabajo de empleado no forma parte de ninguna red dentro de ese perímetro. Debido a que la estación de trabajo de empleado está fuera del perímetro, la solicitud se bloquea.

Acceso de BigQuery desde una VM fuera del proyecto

En este ejemplo, una VM que pertenece al proyecto 458854174376 (data-collector) intenta ejecutar una consulta de BigQuery en un conjunto de datos del proyecto 798816221974 (corp-resources-protected) y se ve rechazada.

La VM usa la siguiente consulta:

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

La consulta muestra lo siguiente:

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

Se genera el siguiente registro de auditoría:

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

En este ejemplo, el violationReason es NETWORK_NOT_IN_SAME_SERVICE_PERIMETER. callerNetwork se incluye, además de callerIp. La dirección IP es privada, y la red se proporciona para que no haya ambigüedad. Aquí se detallan los recursos relevantes en dos lugares: VpcServiceControlAuditMetadata.resourceNames y requestMetadata.callerNetwork (el proyecto que posee la red).

El problema es que el proyecto corp-resources-protected está dentro de un perímetro de servicio, mientras que data-collector, el proyecto que incluye la red a la que pertenece la VM, no. En este caso, se rechazó el acceso como se esperaba.

Consulta entre proyectos de BigQuery

En este ejemplo, una VM que pertenece al proyecto perimeter-network intenta consultar las instancias de BigQuery de dos proyectos diferentes: corp-resources-protected, que se encuentra en el mismo perímetro de servicio que perimeter-network, y corp-resources-public, que no se encuentra en el mismo perímetro.

La VM usa el siguiente comando:

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 consulta muestra lo siguiente:

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

Se genera el siguiente registro de auditoría:

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

Si analizamos callerNetwork y VpcServiceControlAuditMetadata.resourceNames, podemos ver tres proyectos: perimeter-network117961063178 (corp-resources-public) y 690885588241 (corp-resources-protected). Recuerda que corp-resources-public no está en el mismo perímetro de servicio que perimeter-network y corp-resources-protected.

El violationReason, RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER indica que algún recurso de la solicitud está fuera de un perímetro que se aplica a la solicitud. En este caso, ese recurso es corp-resources-public.

Transferencia de archivos de Cloud Storage desde una VM dentro del perímetro

En este ejemplo, en una VM del proyecto perimeter-network, se usa un comando para transferir un archivo de un depósito de Cloud Storage, ubicado en el proyecto corp-resources-protected, a otro depósito, ubicado en el proyecto corp-resources-public.

La VM usa el siguiente comando:

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

El comando muestra lo siguiente:

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

Se genera el siguiente registro de auditoría:

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

En este caso, el registro es menos claro porque el método enumerado es BillingRequiredRead, y la acción que se realiza es move. Esta es una limitación de la funcionalidad del registro de auditoría actual de los Controles del servicio de VPC.

Aunque el motivo es menos claro, este registro de auditoría indica que algún recurso de la solicitud está fuera de un perímetro que se aplica a la solicitud. En este caso, ese recurso es corp-resources-public.

Transferencia de archivos de Cloud Storage desde una VM fuera del perímetro

En este ejemplo, en una VM del proyecto public-network, se usa un comando para transferir un archivo de un depósito de Cloud Storage, ubicado en el proyecto corp-resources-protected, a otro depósito, ubicado en el proyecto corp-resources-public.

corp-resources-protected está protegido por un perímetro de servicio. public-network y corp-resources-public están fuera del perímetro.

La VM usa el siguiente comando:

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

El comando muestra lo siguiente:

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

Se genera el siguiente registro de auditoría:

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

En este ejemplo, el registro de auditoría indica que no se pueden copiar datos en el límite de un perímetro de servicio (ambos recursos están en el registro de auditoría). Recuerda que la solicitud se origina fuera del perímetro (la VM en public-network) y que uno de los depósitos está fuera del perímetro (corp-resources-public-1).

Desde afuera del perímetro, se puede escribir en el depósito corp-resources-public-1, por lo que se aprueba la verificación que falló en el ejemplo anterior. Sin embargo, la verificación posterior para copiar los datos falla.

En este ejemplo se muestra cómo, en ciertas ocasiones, una sola operación del usuario da como resultado varias operaciones internas que deben pasar la aplicación de los Controles del servicio de VPC.

Copia de un conjunto de datos de BigQuery desde una VM dentro del perímetro

En este ejemplo, una VM del proyecto 927005422713 (perimeter-network) intenta copiar un conjunto de datos de BigQuery del proyecto corp-resources-private a corp-resources-public (117961063178). perimeter-network y corp-resources-private comparten un perímetro, mientras que corp-resources-public está fuera del perímetro.

La VM usa el siguiente comando:

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

El comando muestra lo siguiente:

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

Se genera el siguiente registro de auditoría:

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

En este ejemplo, no hay ninguna acción subyacente de la API que muestre todos los recursos en juego en esta solicitud debido a limitaciones del mecanismo de registro y la arquitectura distribuida de BigQuery.

El registro de auditoría indica que la operación falló porque para copiar los datos, BigQuery debe acceder al proyecto de destino (corp-resources-public) mediante la red del proyecto perimeter-network (la fuente de la solicitud). Recuerda que corp-resources-public está fuera del perímetro que protege perimeter-network. Se rechaza la solicitud como un intento de robo de datos a corp-resources-public.

En este ejemplo, se muestra que una operación conceptual, como copiar datos, puede activar varios intentos para acceder a datos de diferentes sistemas de almacenamiento, como Cloud Storage, BigQuery y Bigtable. Según cómo se ejecute la operación, el registro de auditoría que se genera puede ser diferente al comando del usuario original, en especial cuando se realizan varias verificaciones dentro de un servicio determinado y pueden fallar.

Lectura de trabajo de Dataproc desde el proyecto

En este ejemplo, se muestra cómo depurar errores de los Controles del servicio de VPC indirectos que se generan cuando se usan servicios de procesamiento de datos, como Dataproc.

En este ejemplo, un clúster de Dataproc se ejecuta en un proyecto que protegen los Controles del servicio de VPC. Hello-world.py es un trabajo pyspark que intenta acceder a los datos del depósito de Cloud Storage dentro del perímetro y, luego, escribirlo en otro depósito fuera del perímetro, una operación que los Controles del servicio de VPC deberían bloquear.

El siguiente comando se usa para ejecutar Hello-world.py:

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

El comando muestra lo siguiente:

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

Presta atención a la excepción de IO que se produce cuando se llama a saveAsTextFile. Cloud Storage muestra un error 403 con el mensaje Request violates VPC Service Controls. El error indica que la operación del registro de auditoría de Cloud Storage debe revisarse.

En los registros de auditoría del proyecto perimeter-network, en los que se ejecutó el comando, hay un registro de auditoría para la operación 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"
}

Debido a las limitaciones del registro de auditoría, el methodName para Cloud Storage aparece como Read, aunque en realidad es una operación write. El registro de auditoría indica que la operación falló porque una red del proyecto corp-resources-private intentó acceder a los datos (como escribir, en este caso) de un recurso en el depósito corp-resources-public-1. Debido a las limitaciones del registro de auditoría de Cloud Storage, no está claro a qué depósito de proyecto pertenece corp-resources-public-1.

Para identificar el proyecto que contiene corp-resources-public-1, se usa el siguiente comando:

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

El comando muestra lo siguiente:

projectNumber: u'117961063178'

117961063178 es el proyecto corp-resources-public, que está fuera del perímetro externo. Por lo tanto, se espera que falle.

Servicio no compatible con la VIP restringida

Intentar acceder a una API que no es compatible con la VIP restringida de los Controles del servicio de VPC dará como resultado un error 404. Por ejemplo, debido a que los Controles del servicio de VPC no admiten Cloud DNS en la actualidad, la API de Cloud DNS no está disponible cuando se usa la VIP restringida.

Por ejemplo, supongamos que se usa el siguiente comando:

gcloud dns managed-zones list

El comando muestra lo siguiente:

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>

Este tipo de error es el esperado para los servicios que no son compatibles con los Controles del servicio de VPC y que no están disponibles en la VIP restringida. Si se produce este error en un servicio que sí es compatible con los Controles del servicio de VPC, debes verificar las limitaciones del servicio conocidas para este a fin de ver si se trata de una limitación conocida. De lo contrario, el problema debería denunciarse.

Exportación de registros al proyecto fuera del perímetro

En este ejemplo, los Controles del servicio de VPC bloquean una exportación de registro. El destino de la exportación, el proyecto corp-resources-public, está fuera del perímetro de los Controles del servicio de VPC, mientras que el receptor se crea en el proyecto perimeter-network, que está dentro del perímetro.

Por ejemplo, supongamos que se usa el siguiente comando:

gcloud logging sinks describe example-sink

El comando muestra lo siguiente:

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

Se genera el siguiente registro de auditoría:

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

El registro de auditoría se genera para BigQuery, no para Logging. Esto se debe a que BigQuery es el servicio de receptor al que Logging intenta escribir.

La exportación falla porque corp-resources-public está por fuera del perímetro que protege a perimeter-network.

En este ejemplo, se muestra que, en casos en que un servicio de Google Cloud llama a otro mediante una cuenta de servicio administrada de interno a GCP, como p927005422713-439672@gcp-sa-logging.iam.gserviceaccount.com, el “proyecto de red” (en este caso, perimeter-network) de la solicitud se deriva de esa identidad. La misma identidad representa el recurso de exportación de registros en sí.

Este patrón es común en Google Cloud y se aplica a muchos casos de interacción de servicio a servicio.

Extracción de BigQuery a Cloud Storage

En este ejemplo, se describe cómo depurar extracciones de BigQuery con errores a Cloud Storage.

En este ejemplo, corp-resources-private y perimeter-network son proyectos protegidos por un perímetro de servicio. corp-resources-public es un proyecto que está fuera del perímetro.

Supongamos que se usó el siguiente comando:

bq extract babynames.yob2000

El comando muestra lo siguiente:

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.

En este caso, el error no implica de manera específica los Controles del servicio de VPC (se mostraría un error similar si se produjera un error de administración de identidades y accesos).

Se genera el siguiente registro de auditoría:

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

En este registro de auditoría, storage-accessing@example.iam.gserviceaccount.com se identifica como la identidad que intenta ejecutar la operación. En este ejemplo, supongamos que storage-accessing@example.iam.gserviceaccount.com tiene los permisos de IAM necesarios para ejecutar el comando.

Debido a que los permisos de IAM no son el problema, el siguiente paso es verificar las fallas de los Controles del servicio de VPC.

El registro de auditoría del servicio de destino (Cloud Storage) contiene los motivos detallados de la falla:

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

En este registro, queda claro que se están usando los dos proyectos 1004338142803 (corp-resources-private-1) y corp-resources-public para completar el comando. Debido a que estos proyectos no comparten un perímetro, el trabajo de extracción falla.

En este ejemplo, se demuestra que, en las operaciones de varios servicios complejas, los registros de auditoría para los servicios de origen y de destino pueden contener datos de depuración útiles.