Resolva problemas comuns

Esta página apresenta uma lista de vários problemas que pode encontrar ao configurar o VPC Service Controls.

Comportamento inesperado da política com âmbito

Pode notar algumas violações inesperadas dos VPC Service Controls que a sua política com âmbito deve permitir. É um problema conhecido que, se não tiver uma política de acesso ao nível da organização, pode ter alguns problemas inesperados com as suas políticas de acesso com âmbito.

Para resolver este problema, crie uma política de acesso ao nível da organização através do seguinte comando:

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

Substitua o seguinte:

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

Para mais informações, consulte o artigo Crie uma política de acesso.

VPC partilhada

Quando usa a VPC partilhada, um perímetro de serviço que inclua projetos pertencentes a uma rede VPC partilhada também tem de incluir o projeto que alberga a rede. Quando os projetos pertencentes a uma rede de VPC partilhada não estão no mesmo perímetro que o projeto anfitrião, os serviços podem não funcionar como esperado ou podem ser bloqueados na totalidade.

Certifique-se de que o anfitrião de rede de VPC partilhada está no mesmo perímetro de serviço que os projetos ligados à rede.

Não é possível adicionar uma rede VPC

O seguinte erro pode ocorrer quando tenta 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)

Este erro ocorre devido a um dos seguintes motivos:

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

Para resolver este problema, conclua os seguintes passos:

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

    • Antes de validar a rede VPC, certifique-se de que a API Compute Engine está ativada no projeto associado à chamada da API concluindo os seguintes passos:

      1. Na Google Cloud consola, aceda à página APIs e serviços.
        Aceda a 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 em falta, ative-a.
        Ative a API

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

  3. Verifique se o autor da chamada tem a seguinte autorização no projeto anfitrião da rede VPC: compute.networks.get. Esta autorização permite-lhe ver redes de VPC num projeto.

    • Peça ao administrador da organização proprietária do projeto anfitrião da rede VPC para conceder ao autor da chamada uma função do IAM com a autorização compute.networks.get no projeto anfitrião. Por exemplo, a função de leitor da rede de computação.

      Para mais informações sobre a atribuição de funções, consulte o artigo Gerir acesso.

Certifique-se de que lê as limitações associadas à utilização de redes VPC em perímetros de serviço.

Pedidos entre perímetros

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

No entanto, um pedido de um projeto num perímetro para um recurso protegido num outro perímetro é recusado, mesmo que um nível de acesso permita normalmente o pedido.

Por exemplo, suponhamos que o projeto A no perímetro 1 pede um recurso ao projeto B. O recurso no projeto B está protegido pelo perímetro 2. Uma vez que o projeto A está num perímetro, mesmo que um nível de acesso para o perímetro 2 permita normalmente o pedido do recurso protegido, o pedido é recusado.

Use uma das seguintes abordagens para facilitar os pedidos entre perímetros:

  • Use a política de saída e a política de entrada. Para permitir pedidos de outro perímetro a recursos protegidos no seu perímetro, o outro perímetro tem de usar uma política de saída e tem de definir uma política de entrada no seu perímetro.

  • Use pontes de perímetro. As pontes permitem que dois ou mais projetos em perímetros diferentes façam pedidos a quaisquer serviços nesses projetos. Estes pedidos são permitidos mesmo que os serviços estejam protegidos pelos respetivos perímetros.

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

O endereço de email é inválido ou inexistente

Quando atualiza um perímetro que contém um principal eliminado, pode ocorrer o erro The email address is invalid or non-existent.

Para corrigir este problema, tem de remover o endereço de email inválido de todos os perímetros:

  1. Exporte todos os seus perímetros. O seguinte comando de exemplo exporta uma lista de perímetros de serviço no formato YAML:

    gcloud access-context-manager perimeters list \
        --policy=POLICY_NAME \
        --format="json(name,title,description,perimeterType,status,spec,useExplicitDryRunSpec)" \
        > my-perimeters.yaml
  2. Remova o endereço de email inválido do ficheiro my-perimeters.yaml e guarde-o como my-perimeters-updated.yaml.

  3. Substitua em massa todos os seus perímetros.

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

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

Violação da regra de entrada

Uma violação de regra de entrada indica que um cliente da API fora do perímetro tentou aceder a um recurso dentro do perímetro. O perímetro de serviço rejeita o pedido porque não existem regras de entrada nem níveis de acesso correspondentes.

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

  • O nome do perímetro no qual ocorreu a violação da regra de entrada.
  • O recurso dentro do perímetro ao qual o cliente da API fora do perímetro tentou aceder.

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

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

Para resolver este problema, crie uma regra de entrada para o seu perímetro. Para mais informações acerca das regras de entrada, consulte a referência das regras de entrada.

Violação da regra de saída

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

  • Um cliente de API dentro do perímetro tentou aceder a um recurso fora do perímetro.
  • Um pedido de API que envolve um recurso dentro do perímetro e um recurso fora do perímetro. Por exemplo, um cliente do Cloud Storage que chama um comando de cópia em que um contentor está dentro do perímetro e o outro contentor está fora do perímetro.

O perímetro de serviço rejeita o pedido porque não existem regras de saída correspondentes. Uma violação da regra de saída no registo de auditoria inclui os seguintes detalhes:

  • O tipo de origem, como rede ou recurso.
  • A origem, que é um recurso ou uma rede, cujo 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 ao qual o pedido tentou aceder.

No exemplo de violação de regra de saída seguinte, o pedido da API inclui um recurso de projects/5678, que está dentro do perímetro prod-perimeter, e um objeto do contentor 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 este problema, crie uma regra de saída para o seu perímetro. Para mais informações acerca das regras de saída, consulte a referência das regras de saída.

Depuração de pedidos bloqueados pelos VPC Service Controls

O registo de auditoria dos VPC Service Controls é a ferramenta principal para resolver problemas de um pedido bloqueado pelos VPC Service Controls.

Quando o acesso é bloqueado inesperadamente, consulte os registos de auditoria no projeto protegido pelo perímetro de serviço. Estes registos contêm dados significativos sobre os recursos pedidos e o motivo pelo qual o pedido foi recusado. Para informações sobre o diagnóstico dos registos de auditoria, consulte o artigo Aceda ao analisador de violações.

As secções seguintes listam os valores de violationReason que pode encontrar quando usa os VPC Service Controls.

NETWORK_NOT_IN_SAME_SERVICE_PERIMETER

O motivo deste problema pode ser um dos seguintes:

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

O cliente pode enviar o pedido a partir de uma VM do Compute Engine ou do Google Kubernetes Engine, ou a partir de uma rede nas instalações através do Cloud Interconnect ou de uma VPN configurada com uma rede VPC.

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

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

Segue-se um exemplo de uma 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>"
}
]

Onde:

  • <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 projeto que contém a sua rede VPC.
  • <RESOURCE_PROJECT_NUMBER> é o número do projeto do Google Cloud projeto que contém o recurso.

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

Uma violação de entrada devido a NETWORK_NOT_IN_SAME_SERVICE_PERIMETER.

Segue-se um exemplo de uma violação de entrada:

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

Onde:

  • <RESOURCE_PROJECT_NUMBER> é o número do projeto do Google Cloud projeto que contém o recurso.
  • <NETWORK_PROJECT_NUMBER> é o número do projeto do Google Cloud projeto que contém a sua 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 este erro, crie uma regra de entrada ou saída para o seu perímetro.

RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER

Este problema ocorre quando um único pedido está a aceder a vários recursos, mas os recursos não estão no mesmo perímetro de serviço. Este problema ocorre independentemente de onde o cliente se encontra e se o cliente tem acesso aos recursos.

O diagrama seguinte mostra um cliente a aceder a 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 a um cliente que acede a recursos de um projeto fora do perímetro.

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

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

Segue-se um exemplo de uma 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>"
}
]

Onde:

  • <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 projeto Google Cloud que está dentro do perímetro.
  • <RESOURCE_PROJECT_OUTSIDE_THIS_PERIMETER> é o número do projeto do projeto Google Cloud que está fora do perímetro.

Resolução

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

NO_MATCHING_ACCESS_LEVEL

Este problema ocorre quando o endereço IP, o requisito do dispositivo ou a identidade do utilizador não correspondem a nenhuma regra de entrada nem a nenhum nível de acesso atribuído ao perímetro. Isto significa que um cliente que não faz parte da rede tenta aceder aos recursos de rede a partir do exterior do perímetro. Google Cloud Google Cloud Por exemplo, o endereço IP correspondente ao campo callerIp do registo de auditoria não corresponde a nenhum intervalo CIDR definido nos níveis de acesso para o perímetro de serviço.

Se o endereço IP do autor da chamada estiver em falta ou aparecer como um endereço IP interno, esta violação pode dever-se a um serviço que não está integrado com os VPC Service Controls. Google Cloud O motivo pode ser que o serviço tente aceder a um serviço protegido e falhe, como esperado.Google Cloud

Para corrigir este problema, recomendamos que crie uma regra de entrada em vez de um nível de acesso, uma vez que uma regra de entrada oferece um controlo de acesso detalhado.

O diagrama seguinte mostra um cliente a tentar aceder a recursos a partir do exterior do perímetro:

Uma violação de entrada devido a NO_MATCHING_ACCESS_LEVEL.

Segue-se um exemplo de uma 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>"
        }
  ]

Onde:

  • <EMAIL> é o endereço de email da conta de serviço ou do utilizador autenticado.

    Se usar um Google Cloud serviço que o VPC Service Controls não suporta, os endereços de email que pertencem ao domínio google.com são ocultados e substituídos por google-internal. google-internal refere-se a identidades internas pertencentes à Google.

  • <PUBLIC_IP_ADDRESS> é o endereço IP do autor da chamada. Para um autor da chamada a partir da Internet, este será o endereço IPv4 ou IPv6 público.

  • <RESOURCE_PROJECT_NUMBER> é o número do projeto do Google Cloud projeto 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.

Tenha em atenção que, neste caso, metadata.accessLevels pode continuar presente, uma vez que estes níveis de acesso podem não estar especificados no perímetro violado.

SERVICE_NOT_ALLOWED_FROM_VPC

Este problema ocorre quando um cliente tenta aceder a Google Cloud recursos de uma rede VPC. O cliente pode enviar o pedido a partir de uma VM do Compute Engine ou do Google Kubernetes Engine, ou a partir de uma rede nas instalações através do Cloud Interconnect ou de uma VPN configurada com uma rede VPC.

Para corrigir este problema, certifique-se de que o serviço que está a ser chamado é permitido pela configuração de serviços acessíveis por VPC do perímetro de serviço.

Cenários de exemplo

Os exemplos seguintes abrangem problemas que pode encontrar ao usar os VPC Service Controls.

Acesso ao Cloud Storage a partir de instalações locais

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

O pedido gera o seguinte registo de auditoria:

{
 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 num perímetro de serviço. A estação de trabalho do funcionário não faz parte de nenhuma rede dentro desse perímetro. Uma vez que a estação de trabalho do funcionário existe fora do perímetro, o pedido é bloqueado.

Acesso ao BigQuery a partir de uma VM fora do projeto

Neste exemplo, uma VM pertencente ao projeto 458854174376 (data-collector) tenta executar uma consulta do BigQuery num conjunto de dados no projeto 798816221974 (corp-resources-protected) e o acesso é recusado.

A VM usa a seguinte consulta:

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

A consulta devolve o seguinte resultado:

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

É gerado o seguinte registo de auditoria:

{
 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, o violationReason é NETWORK_NOT_IN_SAME_SERVICE_PERIMETER. callerNetwork está incluído, além de callerIp. O endereço IP é privado e a rede é fornecida para o desambiguar. Os recursos relevantes em causa estão listados em dois locais: VpcServiceControlAuditMetadata.resourceNames e requestMetadata.callerNetwork (o projeto proprietário da rede).

O problema é que o projeto corp-resources-protected está dentro de um perímetro de serviço, enquanto data-collector, o projeto que inclui a rede à qual a VM pertence, não está. Neste caso, o acesso é negado, como 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 seguinte 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'

A consulta devolve o seguinte 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

É gerado o seguinte registo de auditoria:

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

Analisando callerNetwork e VpcServiceControlAuditMetadata.resourceNames, podemos ver três projetos: perimeter-network, 117961063178 (corp-resources-public) e 690885588241 (corp-resources-protected). Tenha em atenção que corp-resources-public não está no mesmo perímetro de serviço que perimeter-network e corp-resources-protected.

O erro violationReason, RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER indica que alguns recursos no pedido estão fora de um perímetro que se aplica ao pedido. Neste caso, esse recurso é corp-resources-public.

Mova o ficheiro do Cloud Storage para dentro do perímetro

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

A VM usa o seguinte comando:

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

O comando devolve o seguinte resultado:

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

É gerado o seguinte registo de auditoria:

{
 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 registo é menos claro porque o método indicado é BillingRequiredRead e a ação realizada é move. Esta é uma limitação da funcionalidade de registo de auditoria atual do VPC Service Controls.

Embora o motivo seja menos claro, este registo do registo de auditoria indica que alguns recursos no pedido estão fora de um perímetro que se aplica ao pedido. Neste caso, esse recurso é corp-resources-public.

Mova o ficheiro do Cloud Storage para fora do perímetro

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

O projeto corp-resources-protected está 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 seguinte comando:

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

O comando devolve o seguinte resultado:

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

É gerado o seguinte registo de auditoria:

{
 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 registo 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 registo de auditoria). Recorde que o pedido tem origem fora do perímetro (a VM em public-network) e que um dos contentores existe fora do perímetro (corp-resources-public-1).

Fora do perímetro, é possível escrever no contentor corp-resources-public-1, pelo que a verificação que falhou no exemplo anterior é aprovada. No entanto, a verificação subsequente para copiar os dados falha.

Este exemplo demonstra como, por vezes, uma única operação do utilizador resulta em várias operações internas que têm de passar pela aplicação dos VPC Service Controls.

Cópia do conjunto de dados do BigQuery a partir de uma 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 partilham um perímetro, enquanto corp-resources-public existe fora do perímetro.

A VM usa o seguinte comando:

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

O comando devolve o seguinte resultado:

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

É gerado o seguinte registo de auditoria:

{
 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 existe uma única ação da API subjacente que mostre todos os recursos em jogo neste pedido devido a limitações do mecanismo de registo e da arquitetura distribuída do BigQuery.

O registo do registo de auditoria indica que a operação falhou porque, para copiar os dados, o BigQuery tem de aceder ao projeto de destino (corp-resources-public) através da rede no projeto perimeter-network (a origem do pedido). Lembre-se de que corp-resources-public está fora do perímetro que protege perimeter-network. O pedido é recusado como uma tentativa de exfiltrar dados para corp-resources-public.

Este exemplo ilustra que uma operação conceptual, como copiar dados, pode acionar várias tentativas de acesso a dados de diferentes sistemas de armazenamento, como o Cloud Storage, o BigQuery e o Bigtable. Com base na forma como a operação é executada, o registo de registos de auditoria gerado difere do comando do utilizador original. Além disso, quando são feitas várias verificações num determinado serviço e estas podem falhar, o registo de registo de auditoria gerado tem um aspeto diferente do comando do utilizador original.

Tarefa do Dataproc a ler a partir do projeto

Este exemplo mostra como depurar erros indiretos do VPC Service Controls que ocorrem quando usa serviços de processamento de dados, como o Dataproc.

Neste exemplo, um cluster do Dataproc está a ser executado num projeto protegido pelos VPC Service Controls. Hello-world.py é uma tarefa do PySpark que tenta aceder a dados do contentor do Cloud Storage dentro do perímetro e, em seguida, escrevê-los noutro contentor que existe fora do perímetro. O VPC Service Controls bloqueia a operação que escreve dados num contentor fora do perímetro.

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

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

O comando devolve o seguinte 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].

Tenha em atenção a exceção de E/S que ocorre quando o método saveAsTextFile é chamado. O Cloud Storage devolve um erro 403 com a mensagem Request violates VPC Service Controls. O erro indica que a operação do registo de auditoria do Cloud Storage tem de ser revista.

Nos registos de auditoria do projeto perimeter-network, onde o comando foi executado, existe um registo 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 às limitações dos registos de auditoria, o methodName para o Cloud Storage é apresentado como Read, embora seja, na realidade, uma operação write. O registo do registo de auditoria indica que a operação falhou porque uma rede no projeto corp-resources-private estava a tentar aceder aos dados (escrita, neste caso) de um recurso no contentor corp-resources-public-1. Devido às limitações do registo de auditoria do Cloud Storage, não é claro a que projeto pertence o contentor corp-resources-public-1.

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

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

O comando devolve o seguinte resultado: "projectNumber": "117961063178",

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

Erro devido a serviços não suportados

Alguns Google Cloud serviços dependem de outros Google Cloud serviços como parte da respetiva implementação. Se for usado um serviço não suportado, como o App Engine, num projeto protegido por um perímetro, os recursos do serviço podem não estar acessíveis.

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

Serviço não suportado com VIP restrito

A tentativa de aceder a uma API não suportada pelo VIP restrito dos VPC Service Controls resulta num erro 403. Por exemplo, os VPC Service Controls não suportam o App Engine, pelo que a API App Engine Admin não está disponível quando usa o VIP restrito.

Por exemplo, suponhamos que o seguinte comando é usado para listar todos os serviços do App Engine num perímetro de serviço:

gcloud app services list

O comando devolve o seguinte 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 erro é esperado para serviços que não são suportados pelos VPC Service Controls e não estão disponíveis no VIP restrito. Se este erro ocorrer para um serviço suportado pelo VPC Service Controls, recomendamos que verifique as limitações conhecidas do serviço para ver se se trata de uma limitação conhecida. Caso contrário, o problema tem de ser comunicado.

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

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

Por exemplo, suponhamos que é usado o seguinte comando:

gcloud logging sinks describe example-sink

O comando devolve o seguinte 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

É gerado o seguinte registo de auditoria:

{
 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 registo de auditoria é gerado para o BigQuery e não para o Logging. Isto deve-se ao facto de o BigQuery ser o serviço de destino para o qual o Logging está a tentar escrever.

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

Este exemplo mostra que, nos casos em que um Google Cloud serviço chama outro através de uma conta de serviço gerida que é interna ao Google Cloud>, como o p927005422713-439672@gcp-sa-logging.iam.gserviceaccount.com, o "projeto de rede" (neste caso, perimeter-network) do pedido é derivado dessa identidade. A mesma identidade representa o próprio recurso de exportação de registos.

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

Extração do BigQuery para o Cloud Storage

Este exemplo descreve como depurar extrações do BigQuery com falhas 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.

Suponhamos que foi usado o seguinte comando:

bq extract babynames.yob2000

O comando devolve o seguinte 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.

Neste caso, o erro não implica especificamente o VPC Service Controls. É apresentado um erro semelhante se ocorrer uma falha na gestão de identidade e de acesso.

É gerado o seguinte registo de auditoria:

{
 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 registo de auditoria, storage-accessing@example.iam.gserviceaccount.com é identificado como a identidade que está a tentar executar a operação. Neste exemplo, vamos assumir que storage-accessing@example.iam.gserviceaccount.com tem as autorizações de IAM necessárias para executar o comando.

Uma vez que as autorizações da IAM não são o problema, o passo seguinte é verificar se existem falhas nos VPC Service Controls.

O registo do registo de auditoria para o serviço de destino (Cloud Storage) contém motivos detalhados para a 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"
}

A partir deste registo, é claro que os dois projetos 1004338142803 (corp-resources-private-1) e corp-resources-public estão a ser usados para concluir o comando. Uma vez que esses projetos não partilham um perímetro, a tarefa de extração falha.

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

Acesso ao perímetro através da gateway do Cloud NAT

Neste exemplo, vamos assumir que o projeto A da organização A não está configurado em nenhum perímetro. O projeto B está protegido por um perímetro numa organização diferente. Os recursos privados no projeto A usam o gateway Cloud NAT para alcançar a Internet e as APIs e os serviços Google. É configurado um nível de acesso no projeto B para permitir o acesso com base nos endereços IP do gateway externo do projeto A.

Uma VM pertencente ao projeto A (que pode ser um nó do Google Kubernetes Engine) tenta aceder a um recurso protegido no projeto B, mas a ligação falha, e o seguinte registo do registo 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 regista 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 é ocultado para gce-internal-ip quando os pedidos têm origem num projeto ou numa 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 à Google que ativa automaticamente o acesso privado à Google na sub-rede do recurso e mantém o tráfego para as APIs e os serviços Google internos, em vez de o encaminhar para a Internet através do endereço IP externo do gateway do Cloud NAT.

Neste caso, como o tráfego é encaminhado na rede interna da Google, o campo RequestMetadata.caller_ip do objeto AuditLog é ocultado para gce-internal-ip. Para corrigir este problema, em vez de usar o endereço IP externo do gateway do Cloud NAT no nível de acesso para a lista de autorizações baseada em IP, configure uma regra de entrada para permitir o acesso a partir do projeto ou da conta de serviço.

O que se segue?