En esta página se enumeran varios problemas que pueden surgir al configurar Controles de Servicio de VPC.
Comportamiento inesperado de la política de ámbito
Es posible que observes algunas infracciones inesperadas de Controles de Servicio de VPC que tu política de ámbito debería permitir. Se trata de un problema conocido: si no tienes una política de acceso a nivel de organización, es posible que tengas algunos problemas inesperados con tus políticas de acceso con ámbito.
Para solucionar este problema, crea una política de acceso a nivel de organización con el siguiente comando:
gcloud access-context-manager policies create --organization <var>ORGANIZATION_ID</var> --title <var>POLICY_TITLE</var>
Haz los cambios siguientes:
- ORGANIZATION_ID: el ID de la organización.
- POLICY_TITLE: título legible para personas de tu política de acceso.
Para obtener más información, consulta Crear una política de acceso.
VPC compartida
Cuando se usa una VPC compartida, un perímetro de servicio que incluya proyectos que pertenezcan a una red de VPC compartida también debe incluir el proyecto que aloja la red. Si los proyectos que pertenecen a una red de VPC compartida no están en el mismo perímetro que el proyecto del host, es posible que los servicios no funcionen correctamente 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.
No se puede añadir una red VPC
Puede producirse el siguiente error al intentar añadir una red de VPC a un perímetro de servicio:
ERROR: (gcloud.access-context-manager.perimeters.update) PERMISSION_DENIED: Permission 'compute.networks.get' denied on resource '//compute.googleapis.com/projects/PROJECT_NAME/global/networks/VPC_NETWORK_NAME' (or it may not exist)
Este error se produce por uno de los siguientes motivos:
- La red de VPC no existe.
- La red de VPC existe, pero no tiene ninguna subred.
- El método llamador no tiene el permiso necesario.
Para solucionar este problema, siga estos pasos:
Comprueba si la red de VPC especificada en el mensaje de error existe. Para ello, consulta las redes de tu proyecto.
Antes de verificar la red VPC, asegúrate de que la API Compute Engine esté habilitada en el proyecto asociado a la llamada a la API. Para ello, sigue estos pasos:
En la Google Cloud consola, ve a la página APIs & Services (APIs y servicios).
Ve a APIs y serviciosEn la página APIs & Services (APIs y servicios), comprueba si la API Compute Engine aparece en la lista.
Si falta la API de Compute Engine, habilítala.
Habilita la API
Comprueba si existe al menos una subred en la red de VPC viendo las subredes. Si no hay subredes, añade una subred a la red de VPC.
Comprueba si la persona que llama tiene el siguiente permiso en el proyecto host de la red VPC:
compute.networks.get
. Este permiso te permite ver las redes de VPC de un proyecto.Pide al administrador de la organización propietaria del proyecto host de la red de VPC que conceda al llamante un rol de IAM con el permiso
compute.networks.get
en el proyecto host. Por ejemplo, el rol Lector de red de Compute.Para obtener más información sobre cómo conceder roles, consulta el artículo sobre cómo gestionar el acceso.
Asegúrate de leer las limitaciones asociadas al uso de redes de VPC en perímetros de servicio.
Solicitudes entre perímetros
Normalmente, los niveles de acceso se usan para permitir solicitudes de recursos protegidos que proceden de fuera de un perímetro de servicio y que se dirigen a recursos que se encuentran dentro de un perímetro.
Sin embargo, se deniega una solicitud de un proyecto de un perímetro para acceder a un recurso protegido de otro perímetro, aunque un nivel de acceso normalmente permita la solicitud.
Por ejemplo, supongamos que el proyecto A del perímetro 1 solicita un recurso del proyecto B. El recurso del proyecto B está protegido por el perímetro 2. Como el proyecto A está en un perímetro, aunque un nivel de acceso del perímetro 2 normalmente permita la solicitud del recurso protegido, la solicitud se deniega.
Utiliza uno de los siguientes métodos para facilitar las solicitudes entre perímetros:
Usa políticas de salida y de entrada. Para permitir que las solicitudes de otro perímetro accedan a los recursos protegidos de tu perímetro, el otro perímetro debe usar una política de salida y tú debes definir una política de entrada en tu perímetro.
Usa perímetros puente. Los puentes permiten que dos o más proyectos de perímetros diferentes hagan solicitudes a cualquier servicio de esos proyectos. Estas solicitudes se permiten aunque los servicios estén protegidos por los perímetros correspondientes.
Asegúrate de que tanto el servicio que envía la solicitud como el recurso de destino no estén protegidos por los perímetros. En este caso, la operación se realiza correctamente porque los servicios no están protegidos.
La dirección de correo no es válida o no existe
Al actualizar un perímetro que contiene un principal eliminado, puede producirse un error The email address is invalid or non-existent
.
Para solucionar este problema, debe eliminar la dirección de correo no válida de todos los perímetros:
Exporta todos tus perímetros. El siguiente comando de ejemplo exporta una lista de perímetros de servicio en formato YAML:
gcloud access-context-manager perimeters list \ --policy=POLICY_NAME \ --format="json(name,title,description,perimeterType,status,spec,useExplicitDryRunSpec)" \ > my-perimeters.yaml
Elimina la dirección de correo no válida del archivo
my-perimeters.yaml
y guárdalo comomy-perimeters-updated.yaml
.
Infracciones de las reglas de entrada y salida
El registro de auditoría contiene información sobre las infracciones de las reglas de entrada y salida, lo que te ayuda a comprender las infracciones del perímetro.
Infracción de regla de entrada
Una infracción de una regla de entrada indica que un cliente de API que está fuera del perímetro ha intentado acceder a un recurso que se encuentra dentro del perímetro. El perímetro de servicio rechaza la solicitud porque no hay ninguna regla de entrada ni ningún nivel de acceso que coincida.
Una infracción de una regla de entrada en el registro de auditoría contiene los siguientes detalles:
- Nombre del perímetro en el que se ha producido la infracción de la regla de entrada.
- El recurso que se encuentra dentro del perímetro al que ha intentado acceder el cliente de la API que está fuera del perímetro.
En el siguiente ejemplo de infracción de una regla de entrada, un cliente de API que está fuera del perímetro intenta acceder al segmento de Cloud Storage prod-protected-storage-bucket
que está dentro del perímetro prod-perimeter
.
ingressViolations: [
0: {
targetResource: "projects/1234/buckets/prod-protected-storage-bucket"
servicePerimeter: "accessPolicies/123456789/servicePerimeters/prod-perimeter"
}
]
Para solucionar este problema, crea una regla de entrada para tu perímetro. Para obtener más información sobre las reglas de entrada, consulta la referencia de las reglas de entrada.
Infracción de regla de salida
Una infracción de una regla de salida en el registro de auditoría indica uno de los siguientes eventos:
- Un cliente de API que se encuentra dentro del perímetro ha intentado acceder a un recurso que está fuera del perímetro.
- Una solicitud de API que implica un recurso dentro del perímetro y un recurso fuera del perímetro. Por ejemplo, un cliente de Cloud Storage que llama a un comando de copia en el que un segmento está dentro del perímetro y el otro está fuera.
El perímetro de servicio rechaza la solicitud porque no hay ninguna regla de salida que coincida. Una infracción de una regla de salida en el registro de auditoría incluye los siguientes detalles:
- El tipo de origen, como una red o un recurso.
- La fuente, que es un recurso o una red cuyo perímetro ha sufrido una infracción de salida.
- El perímetro que ha infringido la salida.
- El recurso de destino fuera del perímetro al que ha intentado acceder la solicitud.
En el siguiente ejemplo de infracción de una regla de salida, la solicitud de API incluye un recurso de projects/5678, que está dentro del perímetro prod-perimeter
, y un objeto del segmento de Cloud Storage external-storage-bucket
, que está fuera del perímetro.
egressViolations: [
0: {
sourceType: "Resource"
source: "projects/5678"
targetResource: "projects/4321/buckets/external-storage-bucket/objects/corp-resources.json"
servicePerimeter: "accessPolicies/123456789/servicePerimeters/prod-perimeter"
}
]
Para solucionar este problema, crea una regla de salida para tu perímetro. Para obtener más información sobre las reglas de salida, consulta la referencia de las reglas de salida.
Depurar solicitudes bloqueadas por Controles de Servicio de VPC
El registro de auditoría de Controles de Servicio de VPC es la herramienta principal para depurar una solicitud bloqueada por Controles de Servicio de VPC.
Si el acceso se ha bloqueado de forma inesperada, consulta los registros de auditoría del proyecto protegido por el perímetro de servicio. Estos registros contienen datos significativos sobre los recursos solicitados y el motivo por el que se ha denegado la solicitud. Para obtener información sobre los registros de auditoría, consulta el artículo Diagnosticar problemas con la herramienta para solucionar problemas.
En las secciones siguientes se enumeran los valores de violationReason
que puedes encontrar al usar Controles de Servicio de VPC.
NETWORK_NOT_IN_SAME_SERVICE_PERIMETER
Este problema puede deberse a uno de los siguientes motivos:
- Un cliente de una red de VPC que se encuentra dentro de un perímetro de servicio intenta acceder a un proyecto que no está en el mismo perímetro. Esta solicitud provoca una infracción de salida. Crea una regla de salida para solucionar este problema.
- Un cliente de una red de VPC que está fuera de un perímetro de servicio intenta acceder a un proyecto protegido por el perímetro de servicio. Esta solicitud provoca una infracción de entrada. Crea una regla de entrada para solucionar este problema.
El cliente puede enviar la solicitud desde una máquina virtual de Compute Engine o Google Kubernetes Engine, o desde una red local a través de Cloud Interconnect o una VPN configurada mediante una red de VPC.
En el siguiente diagrama se muestra que se produce una infracción de salida cuando un cliente de una red VPC dentro de un perímetro de servicio intenta acceder a un proyecto fuera del perímetro:
Aquí tienes un ejemplo de una infracción de salida:
egressViolations: [
{
servicePerimeter: "accessPolicies/<POLICY_NAME>/servicePerimeters/<PERIMETER_NAME>"
source: "projects/<NETWORK_PROJECT_NUMBER>"
sourceType: "Network"
targetResource: "projects/<RESOURCE_PROJECT_NUMBER>"
}
]
Donde:
<POLICY_NAME>
es el nombre numérico de tu política de acceso.<PERIMETER_NAME>
es el nombre del perímetro de servicio.<NETWORK_PROJECT_NUMBER>
es el número del proyecto Google Cloud que contiene tu red de VPC.<RESOURCE_PROJECT_NUMBER>
es el número de proyecto del Google Cloud proyecto que contiene el recurso.
En el siguiente diagrama se muestra que se produce una infracción de entrada cuando un cliente que está fuera del perímetro intenta acceder a un proyecto que está dentro del perímetro:
Aquí tienes un ejemplo de una infracción de entrada:
ingressViolations: [
{
targetResource: "projects/<RESOURCE_PROJECT_NUMBER>",
source: "projects/<NETWORK_PROJECT_NUMBER>"
servicePerimeter: "accessPolicies/<POLICY_NAME>/servicePerimeters/<PERIMETER_NAME>"
}
]
Donde:
<RESOURCE_PROJECT_NUMBER>
es el número de proyecto del Google Cloud proyecto que contiene el recurso.<NETWORK_PROJECT_NUMBER>
es el número del proyecto Google Cloud que contiene tu red de VPC.<POLICY_NAME>
es el nombre numérico de tu política de acceso.<PERIMETER_NAME>
es el nombre del perímetro de servicio.
Resolución
Para solucionar este error, cree una regla de entrada o salida para su perímetro.
RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER
Este problema se produce cuando una sola solicitud accede a varios recursos, pero estos no están en el mismo perímetro de servicio. Este problema se produce independientemente de la ubicación del cliente y de si tiene acceso a los recursos.
En el siguiente diagrama se muestra un cliente que accede a recursos de un proyecto fuera del perímetro y de un proyecto dentro del perímetro de servicio:
En el siguiente diagrama se muestra un cliente que accede a recursos de proyectos que se encuentran en dos perímetros de servicio diferentes, pero los perímetros no se comunican entre sí:
Aquí tienes un ejemplo de una infracción de salida:
egressViolations: [
{
servicePerimeter: "accessPolicies/<POLICY_NAME>/servicePerimeters/<PERIMETER_NAME>"
source: "projects/<RESOURCE_PROJECT_INSIDE_THIS_PERIMETER>"
sourceType: "Resource"
targetResource: "projects/<RESOURCE_PROJECT_OUTSIDE_THIS-PERIMETER>"
}
]
Donde:
<POLICY_NAME>
es el nombre numérico de tu política de acceso.<PERIMETER_NAME>
es el nombre del perímetro de servicio.<RESOURCE_PROJECT_INSIDE_THIS_PERIMETER>
es el número de proyecto del Google Cloud proyecto que está dentro del perímetro.<RESOURCE_PROJECT_OUTSIDE_THIS_PERIMETER>
es el número de proyecto del proyecto Google Cloud que está fuera del perímetro.
Resolución
Para resolver este problema, cree una regla de salida para su perímetro.
NO_MATCHING_ACCESS_LEVEL
Este problema se produce cuando la dirección IP, el requisito del dispositivo o la identidad del usuario no coinciden con ninguna regla de entrada ni con ningún nivel de acceso asignado al perímetro. Esto significa que un cliente que no forma parte de la red Google Cloud intenta acceder Google Cloud a los recursos de la red desde fuera del perímetro. Por ejemplo, la dirección IP correspondiente al campo callerIp
del registro de auditoría no coincide con ningún intervalo CIDR definido en los niveles de acceso del perímetro de servicio.
Si falta la dirección IP de la persona que llama o aparece como una dirección IP interna, es posible que esta infracción se deba a un servicio Google Cloud que no esté integrado con Controles de Servicio de VPC. El motivo puede ser que el servicioGoogle Cloud intente acceder a un servicio protegido y falle, como es de esperar.
Para solucionar este problema, te recomendamos que crees una regla de entrada en lugar de un nivel de acceso, ya que las reglas de entrada proporcionan un control de acceso granular.
En el siguiente diagrama se muestra un cliente que intenta acceder a recursos desde fuera del perímetro:
Aquí tienes un ejemplo de una infracción de entrada:
authenticationInfo: {
principalEmail: "EMAIL"
}
requestMetadata: {
callerIp: "<PUBLIC_IP_ADDRESS>"
deviceState: "Cross Organization"
}
ingressViolations: [
{
targetResource: "projects/<RESOURCE_PROJECT_NUMBER>",
servicePerimeter: "accessPolicies/<POLICY_NAME>/servicePerimeters/<PERIMETER-NAME>"
}
]
Donde:
<EMAIL>
es la dirección de correo de la cuenta de servicio o del usuario autenticado.Si usas un Google Cloud servicio que Controles de Servicio de VPC no admite, las direcciones de correo que pertenezcan al dominio
google.com
se ocultarán y se sustituirán porgoogle-internal
.google-internal
hace referencia a las identidades internas propiedad de Google.<PUBLIC_IP_ADDRESS>
es la dirección IP de la persona que llama. En el caso de una persona que llama desde Internet, será la dirección IPv4 o IPv6 pública.<RESOURCE_PROJECT_NUMBER>
es el número de proyecto del Google Cloud proyecto que contiene el recurso.<POLICY_NAME>
es el nombre numérico de tu política de acceso.<PERIMETER_NAME>
es el nombre del perímetro de servicio.
Ten en cuenta que, en este caso, metadata.accessLevels
podría seguir presente, ya que es posible que estos niveles de acceso no se especifiquen en el perímetro infringido.
SERVICE_NOT_ALLOWED_FROM_VPC
Este problema se produce cuando un cliente intenta acceder a Google Cloud recursos de una red de VPC. El cliente puede enviar la solicitud desde una máquina virtual de Compute Engine o Google Kubernetes Engine, o desde una red local a través de Cloud Interconnect o una VPN configurada mediante una red de VPC.
Para solucionar este problema, asegúrate de que el servicio al que se llama esté permitido en la configuración Servicios accesibles de VPC del perímetro de servicio.
Casos de ejemplo
En los siguientes ejemplos se tratan problemas que pueden surgir al usar Controles de Servicio de VPC.
- Acceso a Cloud Storage desde instalaciones locales
- Acceso a BigQuery desde una VM que no pertenece al proyecto
- Consulta de BigQuery entre proyectos
- Mover un archivo de Cloud Storage dentro del perímetro
- Mover un archivo de Cloud Storage fuera del perímetro
- Copia de conjuntos de datos de BigQuery desde una máquina virtual dentro del perímetro
- Lectura de tareas de Dataproc de un proyecto
- Servicio no admitido con VIP restringido
- Exportación de registros a un proyecto fuera del perímetro
- Extracción de BigQuery a Cloud Storage
Acceso a Cloud Storage desde un entorno local
En este ejemplo, Controles de Servicio de VPC bloquea una solicitud de la estación de trabajo de un empleado (identificada por callerIp
) a un segmento de Cloud Storage del 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
está incluido en un perímetro de servicio. La estación de trabajo del empleado no forma parte de ninguna red dentro de ese perímetro. Como la estación de trabajo del empleado está fuera del perímetro, la solicitud se bloquea.
Acceso a 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 le deniega el acceso.
La VM usa la siguiente consulta:
bq --project=corp-resources-protected query 'select count(*) from babynames.yob2000'
La consulta devuelve el siguiente resultado:
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@developer.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
desambiguarla. Los recursos pertinentes en este caso se indican en dos lugares:
VpcServiceControlAuditMetadata.resourceNames
y
requestMetadata.callerNetwork
(el proyecto propietario de 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 lo está. En este caso, se deniega el acceso, como es de esperar.
Consulta de BigQuery entre proyectos
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 está en el mismo perímetro de servicio que perimeter-network
, y corp-resources-public
, que no lo está.
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 devuelve el siguiente resultado:
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 observamos callerNetwork
y VpcServiceControlAuditMetadata.resourceNames
, vemos tres proyectos: perimeter-network
, 117961063178
(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
y el RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER
indican que algún recurso de la solicitud está fuera de un perímetro que se aplica a la solicitud. En este caso, el recurso es corp-resources-public
.
Mover un archivo de Cloud Storage dentro del perímetro
En este ejemplo, una VM del proyecto perimeter-network
usa un comando para mover un archivo de un segmento de Cloud Storage, ubicado en el proyecto corp-resources-protected
, a otro segmento, ubicado en el proyecto corp-resources-public
.
La VM usa el siguiente comando:
gcloud storage mv gs://corp-resources-private-1/yob2000.txt gs://corp-resources-public-1/babynames/
El comando devuelve el siguiente resultado:
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 que aparece es BillingRequiredRead
y la acción realizada es move
. Esta es una limitación de la función de registro de auditoría actual de los Controles de Servicio de VPC.
Aunque el motivo no está tan 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, el recurso es corp-resources-public
.
Mover un archivo de Cloud Storage fuera del perímetro
En este ejemplo, una VM del proyecto public-network
usa un comando para mover un archivo de un segmento de Cloud Storage, ubicado en el proyecto corp-resources-protected
, a otro segmento, ubicado en el proyecto corp-resources-public
.
El proyecto corp-resources-protected
está protegido por un perímetro de servicio. Los proyectos public-network
y corp-resources-public
están fuera del perímetro.
La VM usa el siguiente comando:
gcloud storage mv gs://corp-resources-private-1/yob2000.txt gs://corp-resources-public-1/babynames/
El comando devuelve el siguiente resultado:
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 entre los límites de un perímetro de servicio (ambos recursos están en el registro de auditoría).
Recuerda que la solicitud procede de fuera del perímetro (la VM de public-network
) y que uno de los segmentos se encuentra fuera del perímetro (corp-resources-public-1
).
Desde fuera del perímetro, se puede escribir en el contenedor
corp-resources-public-1
, por lo que la comprobación que ha fallado en el
ejemplo anterior se supera. Sin embargo, la comprobación posterior para copiar los datos no se realiza correctamente.
En este ejemplo se muestra cómo, en ocasiones, una sola operación de usuario da lugar a varias operaciones internas que deben superar la aplicación de Controles de Servicio de VPC.
Copia de conjuntos de datos de BigQuery desde una máquina virtual 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 devuelve el siguiente resultado:
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 una sola acción de API subyacente que muestre todos los recursos que intervienen en esta solicitud debido a las limitaciones del mecanismo de registro y la arquitectura distribuida de BigQuery.
El registro de auditoría indica que la operación ha fallado porque, para copiar los datos, BigQuery debe acceder al proyecto de destino (corp-resources-public
) mediante la red del proyecto perimeter-network
(el origen de la solicitud). Recuerda que corp-resources-public
está fuera del perímetro que protege perimeter-network
. La solicitud se ha denegado porque se ha intentado exfiltrar datos a corp-resources-public
.
En este ejemplo se muestra que una operación conceptual, como copiar datos, puede activar varios intentos de acceder a datos de diferentes sistemas de almacenamiento, como Cloud Storage, BigQuery y Bigtable. En función de cómo se ejecute la operación, el registro de auditoría generado será diferente del comando de usuario original. Además, cuando se realizan varias comprobaciones en un servicio determinado y es posible que fallen, el registro de auditoría generado tiene un aspecto diferente al del comando de usuario original.
Lectura de tareas de Dataproc de un proyecto
En este ejemplo se muestra cómo depurar errores indirectos de Controles de Servicio de VPC que se producen al usar servicios de procesamiento de datos, como Dataproc.
En este ejemplo, un clúster de Dataproc se ejecuta en un proyecto protegido por Controles de Servicio de VPC. Hello-world.py
es un trabajo de PySpark que intenta acceder a los datos de un segmento de Cloud Storage que está dentro del perímetro y, a continuación, escribirlos en otro segmento que está fuera del perímetro.
Controles de Servicio de VPC bloquea la operación que escribe datos en un bucket que está fuera del perímetro.
El siguiente comando se usa para ejecutar Hello-world.py
:
gcloud dataproc jobs submit pyspark hello-world.py --cluster test-cluster-new2
El comando devuelve el siguiente resultado:
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].
Ten en cuenta la excepción de E/S que se produce cuando se llama al método saveAsTextFile
.
Cloud Storage devuelve un error 403
con el mensaje Request violates VPC Service Controls
. El error indica que se debe revisar la operación del registro de auditoría de Cloud Storage.
En los registros de auditoría del proyecto perimeter-network
, donde se ejecutó el comando, hay un registro de auditoría de 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@developer.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 de los registros de auditoría, el methodName
de Cloud Storage se indica como Read
, aunque en realidad es una operación write
. El registro de auditoría indica que la operación ha fallado porque una red del proyecto corp-resources-private
intentaba acceder a los datos (en este caso, escribir) de un recurso del segmento corp-resources-public-1
. Debido a las limitaciones del registro de auditoría de Cloud Storage, no está claro a qué proyecto pertenece el segmento corp-resources-public-1
.
Para identificar el proyecto que contiene corp-resources-public-1
, usa el siguiente comando:
gcloud storage ls gs://corp-resources-public-1 --buckets --log-http 2>&1 | grep projectNumber
El comando devuelve el siguiente resultado:
"projectNumber": "117961063178",
117961063178
es el proyecto corp-resources-public
, que está fuera del perímetro.
Por lo tanto, es normal que se produzca un error.
Error debido a servicios no admitidos
Algunos Google Cloud servicios dependen de otros Google Cloud servicios como parte de su implementación. Si se usa un servicio no compatible, como App Engine, en un proyecto protegido por un perímetro, es posible que no se pueda acceder a los recursos del servicio.
Para obtener información sobre los casos problemáticos conocidos, consulta Limitaciones conocidas del servicio.
Servicio no admitido con VIP restringido
Si intentas acceder a una API que no es compatible con la IP virtual restringida de Controles de Servicio de VPC, se producirá un error 403
. Por ejemplo, Controles de Servicio de VPC no es compatible con App Engine, por lo que la API Admin de App Engine no está disponible cuando se usa la IP virtual restringida.
Por ejemplo, supongamos que se usa el siguiente comando para enumerar todos los servicios de App Engine dentro de un perímetro de servicio:
gcloud app services list
El comando devuelve el siguiente resultado:
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>
Este tipo de error es habitual en los servicios que no son compatibles con Controles de Servicio de VPC y que no están disponibles en la IP virtual restringida. Si se produce este error en un servicio que sí es compatible con Controles de Servicio de VPC, te recomendamos que consultes las limitaciones conocidas del servicio para ver si se trata de una limitación conocida. De lo contrario, debes informar del problema.
Exportación de registros a un proyecto fuera del perímetro
En este ejemplo, los Controles de Servicio de VPC bloquean una exportación de registros.
El destino de exportación, el proyecto corp-resources-public
, está fuera del perímetro de Controles de 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 devuelve el siguiente resultado:
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á fuera del perímetro que protege perimeter-network
.
En este ejemplo se muestra que, en los casos en los que un servicio de Google Cloud llama
a otro mediante una cuenta de servicio gestionada que es interna a Google Cloud,
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.
Este patrón es habitual en Google Cloud y se aplica a numerosos casos de interacción entre servicios.
Extracción de BigQuery a Cloud Storage
En este ejemplo se describe cómo depurar extracciones de BigQuery a Cloud Storage que han fallado.
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 existe fuera del perímetro.
Supongamos que se ha usado el siguiente comando:
bq extract babynames.yob2000
El comando devuelve el siguiente resultado:
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 específicamente a Controles de Servicio de VPC. Se muestra un error similar si se produce un fallo en Gestió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 gestión de identidades y accesos necesarios para ejecutar el comando.
Como los permisos de gestión de identidades y accesos no son el problema, el siguiente paso es comprobar si hay errores en Controles de Servicio de VPC.
El registro de auditoría del servicio de destino (Cloud Storage) contiene los motivos detallados del fallo:
{
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, se puede ver que se están usando los dos proyectos 1004338142803
(corp-resources-private-1
) y corp-resources-public
para completar el comando. Como esos proyectos no comparten un perímetro, la tarea de extracción falla.
En este ejemplo se muestra que, en operaciones complejas de varios servicios, los registros de auditoría de los servicios de origen y de destino pueden contener datos de depuración útiles.
Acceso al perímetro a través de una pasarela de Cloud NAT
En este ejemplo, supongamos que el proyecto A de la organización A no está configurado en ningún perímetro. El proyecto B está protegido por un perímetro de otra organización. Los recursos privados del proyecto A usan la pasarela Cloud NAT para acceder a Internet y a las APIs y servicios de Google. Se configura un nivel de acceso en el proyecto B para permitir el acceso en función de las direcciones IP de la pasarela externa del proyecto A.
Una VM que pertenece al proyecto A (que puede ser un nodo de Google Kubernetes Engine) intenta acceder a un recurso protegido del proyecto B, pero la conexión falla y se genera el siguiente registro de auditoría en el proyecto B:
{
"protoPayload": {
"@type": "type.googleapis.com/google.cloud.audit.AuditLog",
"status": {
"code": 7,
"message": "Request is prohibited by organization's policy. vpcServiceControlsUniqueIdentifier: kmpY9Fgfuhgi2NE90lURjFWuiS1nGRqxCw4L12HdW8h46Un__-_LZw",
"details": [
{
"@type": "type.googleapis.com/google.rpc.PreconditionFailure",
"violations": [
{
"type": "VPC_SERVICE_CONTROLS",
"description": "kmpY9Fgfuhgi2NE90lURjFWuiS1nGRqxCw4L12HdW8h46Un__-_LZw"
}
]
}
]
},
"authenticationInfo": {
"principalEmail": "my-user@example.iam.gserviceaccount.com",
"serviceAccountKeyName": "//iam.googleapis.com/projects/my-project/serviceAccounts/my-user@example.iam.gserviceaccount.com/keys/<code><var>ACCOUNT_KEY</var></code>"
},
"requestMetadata": {
"callerIp": "gce-internal-ip",
"requestAttributes": {},
"destinationAttributes": {}
},
"serviceName": "cloudfunctions.googleapis.com",
"methodName": "google.cloud.functions.v1.CloudFunctionsService.ListFunctions",
"resourceName": "<code><var>PROJECT_ID_1</var></code>",
"metadata": {
"violationReason": "NETWORK_NOT_IN_SAME_SERVICE_PERIMETER",
"resourceNames": [
"projects/<code><var>PROJECT_ID_2</var></code>/locations/-"
],
"securityPolicyInfo": {
"servicePerimeterName": "accessPolicies/<code><var>ACCESS_POLICY</var></code>/servicePerimeters/us_sandbox",
"organizationId": "<code><var>ORGANIZATION_ID</var></code>"
},
"deviceState": "Unknown",
"vpcServiceControlsUniqueId": "kmpY9Fgfuhgi2NE90lURjFWuiS1nGRqxCw4L12HdW8h46Un__-_LZw",
"ingressViolations": [
{
"targetResource": "projects/<code><var>PROJECT_ID_1</var></code>",
"servicePerimeter": "accessPolicies/<code><var>ACCESS_POLICY</var></code>/servicePerimeters/<code><var>PERIMETER_NAME</var></code>",
"source": "<code><var>PROJECT_ID_2</var></code>"
}
],
"@type": "type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
}
},
"insertId": "tzf7fd103i",
"resource": {
"type": "audited_resource",
"labels": {
"service": "cloudfunctions.googleapis.com",
"method": "google.cloud.functions.v1.CloudFunctionsService.ListFunctions",
"project_id": "<code><var>PROJECT_ID_2</var></code>"
}
},
"timestamp": "2024-04-02T19:56:10.770681816Z",
"severity": "ERROR",
"logName": "projects/<code><var>PROJECT_ID_2</var></code>/logs/cloudaudit.googleapis.com%2Fpolicy",
"receiveTimestamp": "2024-04-02T19:56:11.463811603Z"
}
El recurso callerIp
no registra una dirección IP externa. En lugar de la dirección IP externa de la pasarela Cloud NAT, el recurso callerIp
muestra gce-internal-ip
.
El campo callerIp
se oculta y se sustituye por gce-internal-ip
cuando las solicitudes proceden de un proyecto o una organización diferentes y la VM de Compute Engine de origen no tiene una dirección IP externa.
Cloud NAT se integra con Acceso privado de Google para habilitar automáticamente Acceso privado de Google en la subred del recurso y mantener el tráfico a las APIs y los servicios de Google interno en lugar de enrutarlo a Internet mediante la dirección IP externa de la puerta de enlace de Cloud NAT.
En este caso, como el tráfico se enruta en la red interna de Google, el campo RequestMetadata.caller_ip
del objeto AuditLog
se oculta y se muestra como gce-internal-ip
. Para solucionar este problema, en lugar de usar la dirección IP externa de la pasarela Cloud NAT en el nivel de acceso de la lista de permitidas basada en IP, configura una regla de entrada para permitir el acceso desde el proyecto o la cuenta de servicio.
Siguientes pasos
- Consulta cómo obtener errores de Controles de Servicio de VPC de los registros de auditoría.
- Consulta cómo solucionar problemas habituales relacionados con otros servicios Google Cloud .
- Diagnosticar un evento de denegación de acceso con el analizador de infracciones de Controles de Servicio de VPC (versión preliminar).