Solução de problemas comuns

Nesta página, listamos vários problemas que podem ser encontrados ao configurar o VPC Service Controls.

Comportamento inesperado da política com escopo

Talvez você note algumas violações inesperadas do VPC Service Controls que a política com escopo precisa permitir. É um problema conhecido que, se você não tiver uma política de acesso no nível da organização, poderá enfrentar alguns problemas inesperados com as políticas de acesso com escopo.

Para resolver esse problema, crie uma política de acesso no nível da organização usando o seguinte comando:

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

Substitua:

  • ORGANIZATION_ID: o ID da organização.
  • POLICY_TITLE: um título legível para sua política de acesso.

Para mais informações, consulte Criar uma política de acesso.

VPC compartilhada

Ao usar a VPC compartilhada, um perímetro de serviço que inclui projetos pertencentes a uma rede VPC compartilhada também precisa incluir o projeto que hospeda a rede. Quando os projetos pertencentes a uma rede VPC compartilhada não estiverem no mesmo perímetro que o projeto host, os serviços poderão não funcionar como o esperado ou ser totalmente bloqueados.

Verifique se o host da rede VPC compartilhada está no mesmo perímetro de serviço que os projetos conectados à rede.

Não é possível adicionar uma rede VPC

O seguinte erro pode ocorrer ao tentar adicionar uma rede VPC a um perímetro de serviço:

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)

Esse erro ocorre por um dos seguintes motivos:

  • A rede VPC não existe.
  • A rede VPC existe, mas não tem uma sub-rede.
  • O autor da chamada não tem a permissão necessária.

Para resolver esse problema, siga estas etapas:

  1. Verifique se a rede VPC especificada na mensagem de erro existe conferindo as redes no seu projeto.

    • Antes de verificar a rede VPC, verifique se a API Compute Engine está ativada no projeto associado à chamada de API seguindo estas etapas:

      1. No Console do Google Cloud, acesse a página APIs e serviços.
        Acessar APIs e serviços

      2. Na página APIs e serviços, verifique se a API Compute Engine está listada.

      3. Se a API Compute Engine estiver ausente, ative-a.
        Ativar a API

  2. Verifique se pelo menos uma sub-rede existe na rede VPC visualizando as sub-redes. Se não houver sub-redes, adicione uma sub-rede à rede VPC.

  3. Verifique se o autor da chamada tem a seguinte permissão no projeto host da rede VPC: compute.networks.get. Essa permissão permite que você acesse as redes VPC em um projeto.

    • Peça ao administrador da organização proprietária do projeto host da rede VPC para conceder ao autor da chamada um papel do IAM com a permissão compute.networks.get no projeto host. Por exemplo, o papel de leitor da rede do Compute.

      Para mais informações sobre como conceder papéis, consulte Gerenciar acesso.

Leia as limitações associadas ao uso de redes VPC em perímetros de serviço.

Solicitações entre perímetros

Normalmente, os níveis de acesso são usados para permitir solicitações de fora de um perímetro de serviço para recursos protegidos dentro de um perímetro.

No entanto, uma solicitação de um projeto em um perímetro para um recurso protegido em outro perímetro será negada, mesmo que um nível de acesso normalmente permita a solicitação.

Por exemplo, suponha que o Projeto A no Perímetro 1 solicite um recurso do Projeto B. O recurso no Projeto B é protegido pelo Perímetro 2. Como o Projeto A está em um perímetro, a solicitação será negada mesmo se um nível de acesso para o Perímetro 2 geralmente permitir a solicitação do recurso protegido.

Use uma das seguintes abordagens para facilitar as solicitações entre perímetros:

  • Use a política de saída e a política de entrada. Para permitir solicitações de outro perímetro para recursos protegidos no seu perímetro, o outro perímetro precisa usar uma política de saída, e você precisa definir uma política de entrada no seu perímetro.

  • Usar pontes do perímetro. As pontes permitem que dois ou mais projetos em diferentes perímetros façam solicitações a qualquer serviço nesses projetos. Essas solicitações são permitidas mesmo quando os serviços são protegidos pelos respectivos perímetros.

  • Certificar-se de que o serviço solicitante e o recurso de destino não sejam protegidos pelos perímetros. Nesse cenário, a operação é bem-sucedida porque os serviços não estão protegidos.

O endereço de e-mail é inválido ou inexistente

Ao atualizar um perímetro que contém um principal excluído, talvez você encontre a mensagem de erro The email address is invalid or non-existent.

Para corrigir esse problema, realize uma das seguintes tarefas:

  • Remova o endereço de e-mail inválido do perímetro, isso inclui níveis de acesso e regras de entrada e saída.

    É possível usar o console do Google Cloud ou a CLI do Google Cloud.

  • Faça uma operação em massa (somente CLI do Google Cloud) se o endereço de e-mail estiver em ambos, na simulação e no perímetro aplicado.

    1. Consiga todos os perímetros:
      gcloud access-context-manager perimeters list --format=list \
       --policy=<POLICY_NAME> > my-perimeters.yaml
    
    1. Remova o endereço de e-mail inválido do arquivo my-perimeters.yaml e salve-o como my-perimeters-updated.yaml.

    2. Substitua todos os perímetros:

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

Violações das regras de entrada e saída

O registro de auditoria contém informações sobre as violações das regras de entrada e saída que ajudam a entender as violações do perímetro.

Violação da regra de entrada

Uma violação da regra de entrada indica que um cliente da API fora do perímetro tentou acessar um recurso dentro dele. O perímetro de serviço rejeita a solicitação porque não há regras de entrada ou níveis de acesso correspondentes.

Uma violação da regra de entrada no registro de auditoria contém os seguintes detalhes:

  • o nome do perímetro em que ocorreu a violação da regra de entrada;
  • o recurso dentro do perímetro que o cliente da API fora do perímetro tentou acessar.

No exemplo de violação de regra de entrada a seguir, um cliente da API fora do perímetro tenta acessar o bucket prod-protected-storage-bucket do Cloud Storage dentro do perímetro prod-perimeter.

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

Para resolver esse problema, crie uma regra de entrada para o perímetro. Para mais informações sobre as regras de entrada, consulte a Referência de regras de entrada.

Violação da regra de saída

Uma violação da regra de saída no registro de auditoria indica um dos seguintes eventos:

  • Um cliente da API dentro do perímetro tentou acessar um recurso fora do perímetro.
  • Uma solicitação de API que envolve um recurso dentro e um recurso fora do perímetro. Por exemplo, um cliente do Cloud Storage que chama um comando de cópia em que um bucket está dentro do perímetro e o outro está fora do perímetro.

O perímetro de serviço rejeita a solicitação porque não há regras de saída correspondentes. Uma violação da regra de saída no registro de auditoria inclui os seguintes detalhes:

  • o tipo de origem, como rede ou recurso;
  • a origem, que é um recurso ou uma rede, em que o perímetro encontrou uma violação de saída;
  • O perímetro que encontrou uma violação de saída;
  • o recurso de destino fora do perímetro que a solicitação tentou acessar.

No exemplo de violação de regra de saída a seguir, a solicitação da API inclui um recurso de projetos/5678, que está dentro do perímetro prod-perimeter, e um objeto do bucket do Cloud Storage external-storage-bucket, que está fora do 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 resolver esse problema, crie uma regra de saída para o perímetro. Para mais informações sobre as regras de saída, consulte a Referência de regras de saída.

Depuração de solicitações bloqueadas pelo VPC Service Controls

O registro de auditoria do VPC Service Controls é a principal ferramenta para depurar uma solicitação bloqueada pelo VPC Service Controls.

Quando o acesso tiver sido bloqueado inesperadamente, consulte os registros de auditoria no projeto protegido pelo perímetro de serviço. Esses registros contêm dados significativos sobre os recursos solicitados e o motivo da solicitação ter sido negada. Para informações sobre os registros de auditoria, consulte Como diagnosticar problemas usando a solução de problemas.

As seções a seguir listam os valores violationReason que podem ser encontrados ao usar o VPC Service Controls.

NETWORK_NOT_IN_SAME_SERVICE_PERIMETER

O motivo desse problema pode ser um destes:

  • Um cliente em uma rede VPC dentro de um perímetro de serviço tenta acessar um projeto que não está no mesmo perímetro. Essa solicitação resulta em uma violação de saída. Crie uma regra de saída para corrigir esse problema.
  • Um cliente em uma rede VPC fora de um perímetro de serviço tenta acessar um projeto protegido pelo perímetro de serviço. Essa solicitação resulta em uma violação de entrada. Crie uma regra de entrada para corrigir esse problema.

O cliente pode enviar a solicitação a partir de uma VM do Compute Engine ou do Google Kubernetes Engine ou de uma rede no local através do Cloud Interconnect ou de uma VPN configurada usando uma rede VPC.

O diagrama a seguir mostra que ocorre uma violação de saída quando um cliente em uma rede VPC dentro de um perímetro de serviço tenta acessar um projeto fora do perímetro:

Uma violação de saída devido a NETWORK_NOT_IN_SAME_SERVICE_PERIMETER.

Este é um exemplo de violação de saída:

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

Em que:

  • <POLICY_NAME> é o nome numérico da sua política de acesso.
  • <PERIMETER_NAME> é o nome do perímetro de serviço.
  • <NETWORK_PROJECT_NUMBER> é o número do projeto do Google Cloud que contém a rede VPC.
  • <RESOURCE_PROJECT_NUMBER> é o número do projeto do Google Cloud que contém o recurso.

O diagrama a seguir mostra que uma violação de entrada ocorre quando um cliente fora do perímetro tenta acessar um projeto dentro do perímetro:

Uma violação de entrada devido a NETWORK_NOT_IN_SAME_SERVICE_PERIMETER.

Este é um exemplo de violação de entrada:

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

Em que:

  • <RESOURCE_PROJECT_NUMBER> é o número do projeto do Google Cloud que contém o recurso.
  • <NETWORK_PROJECT_NUMBER> é o número do projeto do Google Cloud que contém a rede VPC.
  • <POLICY_NAME> é o nome numérico da sua política de acesso.
  • <PERIMETER_NAME> é o nome do perímetro de serviço.

Resolução

Para resolver esse erro, crie uma regra de entrada ou saída para o perímetro.

RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER

Esse problema ocorre quando uma única solicitação acessa vários recursos, mas os recursos não estão no mesmo perímetro de serviço. Esse problema ocorre independentemente de onde o cliente está localizado e se ele tem acesso aos recursos.

O diagrama a seguir mostra um cliente acessando recursos de um projeto fora do perímetro e de um projeto dentro do perímetro de serviço:

Uma violação de saída devido ao acesso de um cliente a recursos de um projeto fora do perímetro.

O diagrama a seguir mostra o acesso de um cliente a recursos de projetos que estão em dois perímetros de serviço diferentes, mas os perímetros não se comunicam entre si:

Uma violação de saída devido ao acesso de um cliente a recursos de projetos que estão em dois perímetros de serviço diferentes.

Este é um exemplo de violação de saída:

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

Em que:

  • <POLICY_NAME> é o nome numérico da sua política de acesso.
  • <PERIMETER_NAME> é o nome do perímetro de serviço.
  • <RESOURCE_PROJECT_INSIDE_THIS_PERIMETER> é o número do projeto do Google Cloud que está dentro do perímetro.
  • <RESOURCE_PROJECT_OUTSIDE_THIS_PERIMETER> é o número do projeto do Google Cloud que está fora do perímetro.

Resolução

Para resolver esse problema, crie uma regra de saída para o perímetro.

NO_MATCHING_ACCESS_LEVEL

Esse problema ocorre quando o endereço IP, o requisito do dispositivo ou a identidade do usuário não corresponde a nenhuma regra de entrada ou nível de acesso atribuído ao perímetro. Isso significa que um cliente que não faz parte da rede do Google Cloud tenta acessar recursos de rede do Google Cloud fora do perímetro. Por exemplo, o endereço IP correspondente ao campo callerIp do registro de auditoria não corresponde a nenhum intervalo CIDR definido nos níveis de acesso do perímetro de serviço.

Se o endereço IP do autor da chamada estiver ausente ou aparecer como um endereço IP interno, essa violação pode ser causada por um serviço do Google Cloud não integrado ao VPC Service Controls. Isso pode acontecer porque o serviço do Google Cloud tenta acessar um serviço protegido e falha, conforme esperado.

Para corrigir esse problema, recomendamos criar uma regra de entrada em vez de um nível de acesso, porque uma regra de entrada fornece controle de acesso granular.

O diagrama a seguir mostra a tentativa de acesso de um cliente a recursos de fora do perímetro:

Uma violação de entrada devido a NO_MATCHING_ACCESS_LEVEL.

Este é um exemplo de violação 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>"
        }
  ]

Em que:

  • <EMAIL> é o endereço de e-mail da conta de serviço ou do usuário autenticado.

    Se você usar um serviço do Google Cloud que não seja compatível com o VPC Service Controls, os endereços de e-mail que pertencem ao domínio google.com serão substituídos por google-internal. google-internal se refere a identidades internas do Google.

  • <PUBLIC_IP_ADDRESS> é o endereço IP do autor da chamada. Em relação a um autor da chamada via Internet, este é o endereço IPv4 ou IPv6 público.

  • <RESOURCE_PROJECT_NUMBER> é o número do projeto do Google Cloud que contém o recurso.

  • <POLICY_NAME> é o nome numérico da sua política de acesso.

  • <PERIMETER_NAME> é o nome do perímetro de serviço.

Nesse caso, metadata.accessLevels ainda pode estar presente, porque esses níveis de acesso podem não ser especificados no perímetro violado.

SERVICE_NOT_ALLOWED_FROM_VPC

Esse problema ocorre quando um cliente tenta acessar recursos do Google Cloud por uma rede VPC. O cliente pode enviar a solicitação a partir de uma VM do Compute Engine ou do Google Kubernetes Engine ou de uma rede local através do Cloud Interconnect ou de uma VPN configurada usando uma rede VPC.

Para corrigir esse problema, verifique se o serviço que está sendo chamado é permitido pela configuração de serviços acessíveis pela VPC do perímetro de serviço.

Exemplos de cenários

Os exemplos a seguir abordam possíveis problemas ao usar o VPC Service Controls.

Acesso ao Cloud Storage do local

Neste exemplo, o VPC Service Controls bloqueia uma solicitação de uma estação de trabalho de funcionário (identificada por callerIp) para um bucket do Cloud Storage no projeto corp-storage.

A solicitação gera o registro de auditoria a seguir:

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

O projeto corp-storage está incluído em um perímetro de serviço. A estação de trabalho do funcionário não faz parte de nenhuma rede dentro desse perímetro. Como a estação de trabalho do funcionário existe fora do perímetro, a solicitação é bloqueada.

Acesso ao BigQuery da VM fora do projeto

Neste exemplo, uma VM pertencente ao projeto 458854174376 (data-collector) tenta executar uma consulta do BigQuery em um conjunto de dados no projeto 798816221974 (corp-resources-protected), o que é negado.

A VM usa a consulta a seguir:

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

A consulta retorna a saída a seguir:

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

O registro de auditoria a seguir é gerado:

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

Neste exemplo, violationReason é NETWORK_NOT_IN_SAME_SERVICE_PERIMETER. callerNetwork é incluído, além de callerIp. O endereço IP é particular e a rede é fornecida para diferenciá-lo. Os recursos relevantes em questão são listados em dois lugares: VpcServiceControlAuditMetadata.resourceNames e requestMetadata.callerNetwork (o projeto que é proprietário da rede).

O problema é que o projeto corp-resources-protected está dentro de um perímetro de serviço, mas o projeto que inclui a rede a que pertence a VM, data-collector, não está. Neste caso, o acesso é negado conforme o esperado.

Consulta do BigQuery entre projetos

Neste exemplo, uma VM pertencente ao projeto perimeter-network tenta consultar as instâncias do BigQuery de dois projetos diferentes: corp-resources-protected, que está no mesmo perímetro de serviço que perimeter-network, e corp-resources-public, que não está.

A VM usa o comando a seguir:

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'

A consulta retorna a saída a seguir:

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

O registro de auditoria a seguir é gerado:

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

Observando callerNetwork e VpcServiceControlAuditMetadata.resourceNames, vemos três projetos: perimeter-network, 117961063178 (corp-resources-public) e 690885588241 (corp-resources-protected). Lembre-se de que corp-resources-public não está no mesmo perímetro de serviço que perimeter-network e corp-resources-protected.

O valor de violationReason, RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER, indica que algum recurso na solicitação está fora de um perímetro que se aplica à solicitação. Neste caso, o recurso é corp-resources-public.

Mover o arquivo do Cloud Storage dentro do perímetro

Neste exemplo, uma VM no projeto perimeter-network usa um comando para mover um arquivo de um bucket do Cloud Storage, localizado no projeto corp-resources-protected, para outro bucket, localizado no projeto corp-resources-public.

A VM usa o comando a seguir:

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

O comando retorna a seguinte saída:

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

O registro de auditoria a seguir é gerado:

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

Neste caso, o registro é menos claro porque o método listado é BillingRequiredRead e a ação realizada é move. Essa é uma limitação da atual funcionalidade de registro de auditoria do VPC Service Controls.

O motivo é menos claro, mas esse registro de auditoria indica que algum recurso na solicitação está fora de um perímetro que se aplica à solicitação. Neste caso, o recurso é corp-resources-public.

Mover o arquivo do Cloud Storage fora do perímetro

Neste exemplo, uma VM no projeto public-network usa um comando para mover um arquivo de um bucket do Cloud Storage, localizado no projeto corp-resources-protected, para outro bucket, localizado no projeto corp-resources-public.

O projeto corp-resources-protected é protegido por um perímetro de serviço. Os projetos public-network e corp-resources-public existem fora do perímetro.

A VM usa o comando a seguir:

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

O comando retorna a seguinte saída:

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

O registro de auditoria a seguir é gerado:

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

Neste exemplo, o registro de auditoria indica que não é possível copiar dados através do limite de um perímetro de serviço (ambos os recursos estão no registro de auditoria). Lembre-se de que a solicitação é originada de fora do perímetro (a VM em public-network) e que um dos buckets existe fora do perímetro (corp-resources-public-1).

De fora do perímetro, é possível gravar no bucket corp-resources-public-1, portanto, a verificação que falhou no exemplo anterior é aprovada. No entanto, a verificação seguinte para realmente copiar os dados falhará.

Neste exemplo, demonstramos como às vezes uma única operação do usuário resulta em várias operações internas que precisam aprovar a aplicação do VPC Service Controls.

Cópia do conjunto de dados do BigQuery da VM dentro do perímetro

Neste exemplo, uma VM no projeto 927005422713 (perimeter-network) tenta copiar um conjunto de dados do BigQuery do projeto corp-resources-private para corp-resources-public (117961063178). perimeter-network e corp-resources-private compartilham um perímetro, enquanto corp-resources-public existe fora do perímetro.

A VM usa o comando a seguir:

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

O comando retorna a seguinte saída:

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

O registro de auditoria a seguir é gerado:

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

Neste exemplo, não há uma ação de API subjacente única que mostre todos os recursos em jogo nessa solicitação devido às limitações do mecanismo de geração de registros e da arquitetura distribuída do BigQuery.

O registro de auditoria indica que a operação falhou porque, para copiar os dados, o BigQuery precisa acessar o projeto de destino (corp-resources-public) usando a rede no projeto perimeter-network (a origem da solicitação). Lembre-se de que corp-resources-public está fora do perímetro que protege perimeter-network. A solicitação é negada como uma tentativa de exfiltrar dados para corp-resources-public.

Neste exemplo, mostramos que uma operação conceitual, como a cópia de dados, pode acionar várias tentativas de acessar dados de diferentes sistemas de armazenamento, como Cloud Storage, BigQuery e Bigtable. Com base em como a operação é executada, o registro de auditoria gerado é diferente do comando do usuário original. Além disso, quando várias verificações dentro de um determinado serviço são feitas e podem falhar, o registro de auditoria gerado é diferente do comando do usuário original.

Leitura de job do Dataproc do projeto

Neste exemplo, mostramos como depurar erros indiretos do VPC Service Controls que ocorrem quando são usados serviços de processamento de dados, como o Dataproc.

Neste exemplo, um cluster do Dataproc é executado em um projeto protegido pelo VPC Service Controls. Hello-world.py é um job do Pyspark que tenta acessar dados pelo bucket do Cloud Storage dentro do perímetro e gravá-los em outro bucket fora dele. O VPC Service Controls bloqueia a operação que grava dados em um bucket fora do perímetro.

O comando a seguir é usado para executar Hello-world.py:

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

O comando retorna a seguinte saída:

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

Observe a exceção de E/S que ocorre quando o método saveAsTextFile é chamado. O Cloud Storage retorna um erro 403 com a mensagem Request violates VPC Service Controls. O erro indica que a operação do registro de auditoria do Cloud Storage precisa ser revisada.

Nos registros de auditoria do projeto perimeter-network, em que o comando foi executado, há um registro de auditoria para a operação 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"
}

Devido a limitações do registro de auditoria, o methodName do Cloud Storage é listado como Read, apesar de ser uma operação write. O registro de auditoria indica que a operação falhou porque uma rede no projeto corp-resources-private tentou acessar os dados (neste caso, gravação) de um recurso no bucket corp-resources-public-1. Devido às limitações do registro de auditoria do Cloud Storage, não está claro a que bucket do projeto corp-resources-public-1 pertence.

Para identificar o projeto que contém corp-resources-public-1, use este comando:

gcloud storage ls gs://corp-resources-public-1 --buckets --log-http 2>&1 | grep projectNumber

O comando retorna a seguinte saída: "projectNumber": "117961063178",

117961063178 é o projeto corp-resources-public, que está fora do perímetro. Portanto, a falha é esperada.

Erro devido a serviços sem suporte

Alguns serviços do Google Cloud dependem de outros como parte da implementação. Se um serviço sem suporte, como o App Engine, for usado dentro de um projeto protegido por um perímetro, os recursos do serviço poderão não ser acessíveis.

Para informações sobre casos problemáticos conhecidos, consulte Limitações de serviço conhecidas.

Serviço incompatível com VIP restrito

A tentativa de acessar uma API sem suporte do VIP restrito do VPC Service Controls resultará em um erro 403. Por exemplo, o VPC Service Controls não é compatível com o App Engine. Portanto, a API App Engine Admin não está disponível ao usar o VIP restrito.

Por exemplo, suponha que o comando a seguir seja usado para listar todos os serviços do App Engine em um perímetro de serviço:

gcloud app services list

O comando retorna a seguinte saída:

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>

Esse tipo de erro é esperado para serviços incompatíveis com o VPC Service Controls e indisponíveis no VIP restrito. Se esse erro ocorrer em um serviço compatível com o VPC Service Controls, recomendamos que você verifique as limitações conhecidas do serviço para ver se é uma limitação conhecida. Caso contrário, o problema precisa ser relatado.

Exportação de registro para projeto fora do perímetro

Neste exemplo, uma exportação de registro é bloqueada pelo VPC Service Controls. O destino da exportação, projeto corp-resources-public, está fora do perímetro do VPC Service Controls, e o coletor é criado no projeto perimeter-network, que está dentro do perímetro.

Por exemplo, suponha que o comando a seguir seja usado:

gcloud logging sinks describe example-sink

O comando retorna a seguinte saída:

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

O registro de auditoria a seguir é gerado:

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

O registro de auditoria é gerado para o BigQuery, não para o Logging. Isso ocorre porque o BigQuery é o serviço de coletor em que o Logging está tentando gravar.

A exportação falha porque corp-resources-public existe fora do perímetro que protege perimeter-network.

Neste exemplo, mostramos que, nos casos em que um serviço do Google Cloud chama outro usando uma conta de serviço gerenciado interna do Google Cloud, como p927005422713-439672@gcp-sa-logging.iam.gserviceaccount.com, o "projeto de rede" (neste caso, perimeter-network) da solicitação é derivado dessa identidade. A mesma identidade representa o próprio recurso de exportação de registro.

Esse padrão é comum no Google Cloud e se aplica a vários casos de interação entre serviços.

Extração do BigQuery para o Cloud Storage

Neste exemplo, descrevemos como depurar extrações do BigQuery com falha para o Cloud Storage.

Neste exemplo, corp-resources-private e perimeter-network são projetos protegidos por um perímetro de serviço. corp-resources-public é um projeto que existe fora do perímetro.

Suponha que o comando a seguir tenha sido usado:

bq extract babynames.yob2000

O comando retorna a seguinte saída:

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.

Nesse caso, o erro não implica especificamente no VPC Service Controls. Um erro semelhante será mostrado se houver uma falha no gerenciamento de identidade e acesso.

O registro de auditoria a seguir é gerado:

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

Neste registro de auditoria, storage-accessing@example.iam.gserviceaccount.com é identificado como a identidade que tenta executar a operação. Neste exemplo, suponha que storage-accessing@example.iam.gserviceaccount.com tenha as permissões necessárias do IAM para executar o comando.

Como as permissões do IAM não são o problema, a próxima etapa é verificar se existem falhas no VPC Service Controls.

O registro de auditoria para o serviço de destino (Cloud Storage) inclui motivos detalhados da falha:

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

Segundo esse registro, está claro que os dois projetos, 1004338142803 (corp-resources-private-1) e corp-resources-public, estão sendo usados para executar o comando. Como esses projetos não compartilham um perímetro, o job de extração falha.

Esse exemplo ilustra que, em operações complexas de vários serviços, os registros de auditoria dos serviços tanto de origem quanto de destino podem conter dados de depuração úteis.

Acesso ao perímetro pelo gateway NAT do Cloud

Neste exemplo, suponha que o projeto A da Org A não esteja configurado em nenhum perímetro. O Projeto B é protegido por um perímetro em uma organização diferente. Os recursos particulares no projeto A usam o gateway do Cloud NAT para acessar a Internet e as APIs e serviços do Google. Um nível de acesso é configurado no projeto B para permitir o acesso com base nos endereços IP do gateway externo do projeto A.

Uma VM que pertence ao projeto A (que pode ser um nó do Google Kubernetes Engine) tenta acessar um recurso protegido no projeto B, mas a conexão falha, e o seguinte registro de registro de auditoria é gerado no projeto 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"
}

O recurso callerIp não registra um endereço IP externo. Em vez do endereço IP externo do gateway do Cloud NAT, o recurso callerIp mostra gce-internal-ip.

O campo callerIp é editado para gce-internal-ip quando as solicitações originam de um projeto ou organização diferente e a VM do Compute Engine de origem não tem um endereço IP externo.

O Cloud NAT tem uma integração com o Acesso privado do Google que ativa automaticamente o Acesso privado do Google na sub-rede do recurso e mantém o tráfego para as APIs e serviços do Google interno, em vez de encaminhamento para a Internet usando o endereço IP externo do gateway do Cloud NAT.

Nesse caso, como o tráfego é roteado dentro da rede interna do Google, o campo RequestMetadata.caller_ip do objeto AuditLog é substituído por gce-internal-ip. Para corrigir isso, em vez de usar o endereço IP externo do gateway do Cloud NAT no nível de acesso para a lista de permissões baseada em IP, configure uma regra de entrada para permitir o acesso do projeto ou da conta de serviço.

A seguir