
GCP
Artifact Registry para Maven: Standard, Remote e Virtual Repositories contra dependency confusion
Engineering Handbook - Capitulo 09
Google Cloud Master Journey 2026
Engineering Handbook · Capítulo 09
Como organizei pacotes Java privados, criei um cache controlado para o Maven Central e usei um repositório virtual para definir precedência entre dependências internas e externas.
Este artigo faz parte da série Google Cloud Master Journey 2026, em que estou transformando laboratórios práticos em capítulos de um Engineering Handbook sobre Cloud Engineering, DevSecOps, arquitetura e segurança.
A proposta não é apenas registrar comandos executados. Quero transformar cada laboratório em um material que responda perguntas de engenharia:
- por que uma organização precisa controlar dependências;
- qual diferença existe entre armazenar, fazer cache e agregar repositórios;
- como o Maven publica e resolve pacotes;
- onde a autenticação do Artifact Registry entra;
- como a prioridade de upstreams reduz risco de dependency confusion;
- quais limitações permanecem mesmo depois de criar um repositório virtual;
- como estruturar essa solução entre projetos, equipes e ambientes;
- como evoluir o laboratório para uma arquitetura de produção.
Neste capítulo, o tema é gerenciamento seguro de dependências Java com Artifact Registry.
O laboratório
O laboratório usado como base foi Securing Container Builds (GSP1185).
Apesar do nome mencionar builds de contêiner, a prática concentra-se no gerenciamento de pacotes Maven que podem alimentar aplicações e imagens de contêiner posteriormente.
Durante o laboratório, construí três modos de repositório:
- Standard Repository, para armazenar pacotes Java privados;
- Remote Repository, para atuar como proxy e cache do Maven Central;
- Virtual Repository, para combinar os dois upstreams por meio de uma única configuração.
O resultado é uma arquitetura em que o cliente não precisa consultar diretamente várias origens.
O que vamos construir
Ao final do laboratório, o fluxo ficou assim:
Código Java
→ Maven
→ repositório virtual
→ pacote privado, quando existir
→ cache remoto, quando for dependência pública
→ Maven Central apenas em caso de cache miss
Também configuramos uma rota separada de publicação:
mvn deploy
→ Standard Repository
Essa separação é importante:
- publicação escreve no repositório privado;
- resolução de dependências lê pelo repositório virtual;
- dependências públicas passam pelo cache remoto;
- prioridade evita que um pacote público substitua facilmente um pacote interno de mesmas coordenadas.
O problema: dependências também fazem parte da supply chain
Quando uma aplicação executa:
mvn compile
ela não compila apenas o código escrito pela equipe.
O Maven pode baixar:
- bibliotecas;
- plugins;
- parent POMs;
- metadados;
- artefatos transitivos;
- versões de snapshots;
- componentes vindos de repositórios externos.
Uma dependência externa pode alterar o comportamento do build sem que o código da aplicação mude.
Por isso, controlar dependências não é apenas uma questão de velocidade.
É uma decisão de:
- confiabilidade;
- segurança;
- governança;
- rastreabilidade;
- disponibilidade;
- conformidade;
- reprodutibilidade.
Por que apontar diretamente para o Maven Central é limitado
O Maven Central é essencial para o ecossistema Java, mas uma organização que depende diretamente de um registry público enfrenta alguns riscos operacionais:
- indisponibilidade temporária;
- variação de latência;
- dependência de conectividade externa;
- ausência de uma camada central de auditoria;
- dificuldade para aplicar políticas uniformes;
- downloads repetidos;
- risco de confusão entre pacotes públicos e privados;
- menor controle sobre quais origens os clientes consultam.
Um Remote Repository não elimina a dependência do upstream.
Ele adiciona uma camada controlada entre o cliente e a fonte externa.
Os três modos do Artifact Registry
Artifact Registry possui diferentes modos de repositório.
Neste laboratório, utilizamos os três que formam o padrão mais importante para gerenciamento de dependências.
| Modo | Responsabilidade | Armazena conteúdo? | Origem do conteúdo |
|---|---|---|---|
| Standard | Pacotes privados publicados pela organização | Sim | Upload ou deploy direto |
| Remote | Proxy e cache de uma origem upstream | Sim, após solicitação | Maven Central |
| Virtual | Ponto único de acesso a upstreams | Não armazena diretamente | Standard e Remote |
Um detalhe arquitetural importante é que o modo do repositório não pode ser transformado depois de sua criação.
A escolha precisa ser feita no design inicial.
Task 1 — Standard Repository
O que é um Standard Repository
Standard Repository é o modo usado para armazenar artefatos privados diretamente.
No laboratório, criamos:
gcloud artifacts repositories create container-dev-java-repo \
--repository-format=maven \
--location=us-central1 \
--description="Java package repository for Container Dev Workshop"
O repositório criado tinha:
format: MAVEN
mode: STANDARD_REPOSITORY
location: us-central1
Esse repositório passa a ser a fonte controlada para bibliotecas internas.
Pacotes privados como produto interno
Em uma organização, um pacote Maven privado pode representar:
- SDK interno;
- biblioteca de autenticação;
- cliente de API;
- componente de observabilidade;
- modelo de domínio;
- módulo de segurança;
- integração compartilhada;
- design system de backend;
- framework corporativo.
Sem um registry interno, equipes podem recorrer a práticas frágeis:
- copiar JARs manualmente;
- publicar binários em buckets sem metadados Maven;
- duplicar código;
- usar repositórios pessoais;
- incluir arquivos binários no Git;
- depender de compartilhamento informal.
Um Standard Repository transforma a biblioteca em um artefato versionado e consumível pelo ecossistema Maven.
Task 2 — Configurando Maven para Artifact Registry
O comando central foi:
gcloud artifacts print-settings mvn \
--repository=container-dev-java-repo \
--location=us-central1
Ele gera as configurações que precisam ser adicionadas ao projeto.
Três seções são especialmente importantes:
distributionManagement
repositories
build/extensions
Cada uma resolve uma responsabilidade diferente.
distributionManagement
Essa seção define para onde o projeto publica seus artefatos.
<distributionManagement>
<snapshotRepository>
<id>artifact-registry</id>
<url>
artifactregistry://us-central1-maven.pkg.dev/PROJECT_ID/container-dev-java-repo
</url>
</snapshotRepository>
<repository>
<id>artifact-registry</id>
<url>
artifactregistry://us-central1-maven.pkg.dev/PROJECT_ID/container-dev-java-repo
</url>
</repository>
</distributionManagement>
Modelo mental:
mvn deploy
→ distributionManagement
→ destino de publicação
Essa seção não é a principal responsável por resolver dependências.
Ela define o destino do pacote produzido pelo projeto.
repositories
Essa seção informa onde Maven pode procurar artefatos consumidos pela aplicação.
<repositories>
<repository>
<id>artifact-registry</id>
<url>
artifactregistry://us-central1-maven.pkg.dev/PROJECT_ID/container-dev-java-repo
</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
Modelo mental:
mvn compile
→ repositories
→ origens de leitura
A diferença é fundamental:
| Operação | Seção |
|---|---|
| Publicar o pacote | distributionManagement |
| Baixar dependências | repositories |
artifactregistry-maven-wagon
O protocolo usado na URL não é HTTP comum:
artifactregistry://
O Maven precisa de um transport provider capaz de:
- autenticar no Google Cloud;
- obter credenciais;
- comunicar-se com Artifact Registry;
- enviar e baixar arquivos;
- integrar o protocolo ao ciclo Maven.
O laboratório adicionou:
<build>
<extensions>
<extension>
<groupId>com.google.cloud.artifactregistry</groupId>
<artifactId>artifactregistry-maven-wagon</artifactId>
<version>2.2.0</version>
</extension>
</extensions>
</build>
Por que usar .mvn/extensions.xml
O laboratório também criou:
<extensions
xmlns="http://maven.apache.org/EXTENSIONS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/EXTENSIONS/1.0.0 https://maven.apache.org/xsd/core-extensions-1.0.0.xsd">
<extension>
<groupId>com.google.cloud.artifactregistry</groupId>
<artifactId>artifactregistry-maven-wagon</artifactId>
<version>2.2.0</version>
</extension>
</extensions>
Esse arquivo é carregado como core extension antes do pom.xml.
Isso importa quando o projeto precisa resolver:
- parent POM;
- build extension;
- plugin;
- componente necessário antes de o restante do POM ser processado.
Colocar a extensão apenas no bloco <build> pode ser tarde demais para determinados cenários de resolução antecipada.
Publicando o pacote privado
Depois da configuração, executamos:
mvn deploy -DskipTests
O fluxo foi:
O Artifact Registry armazenou mais do que um JAR isolado.
Um pacote Maven pode incluir:
- arquivo
.jar; pom.xml;- checksums;
- metadados de versão;
- snapshot metadata;
- arquivos adicionais associados ao release.
Releases e snapshots
O Standard Repository do laboratório foi criado sem política de versão específica.
Assim, ele aceita releases e snapshots.
Em produção, eu avaliaria separar:
maven-releases
maven-snapshots
Vantagens:
- permissões diferentes;
- retenção diferente;
- imutabilidade mais clara;
- menor risco de promover snapshot;
- políticas de limpeza específicas;
- auditoria mais simples.
Task 3 — Remote Repository
O que é um Remote Repository
O repositório remoto foi criado como proxy do Maven Central:
gcloud artifacts repositories create maven-central-cache \
--project=${PROJECT_ID} \
--repository-format=maven \
--location=us-central1 \
--description="Remote repository for Maven Central caching" \
--mode=remote-repository \
--remote-repo-config-desc="Maven Central" \
--remote-mvn-repo=MAVEN-CENTRAL
O fluxo funciona assim:
- Maven solicita um artefato.
- Artifact Registry verifica se há uma cópia no cache.
- Em cache hit, a cópia armazenada é retornada.
- Em cache miss, Artifact Registry consulta o Maven Central.
- O artefato é armazenado no Remote Repository.
- Solicitações futuras usam o cache.
Benefícios do cache remoto
- Confiabilidade: depois que um artefato foi armazenado, builds futuros podem consumir a cópia em cache.
- Controle: os clientes consultam uma origem administrada pela organização, não diretamente o registry público.
- Auditoria: a organização ganha um ponto central para observar os pacotes solicitados.
- Latência: artefatos em cache podem ser entregues a partir de uma região próxima ao ambiente de build.
- Redução de tráfego externo: downloads repetidos deixam de atingir o upstream toda vez.
- Base para políticas: o repositório remoto pode fazer parte de uma arquitetura com IAM, VPC Service Controls e upstreams controlados.
O que um Remote Repository não é
Ele não é uma cópia completa do Maven Central.
O cache é preenchido sob demanda.
pacote nunca solicitado
→ não está no cache
Também não significa independência total do upstream.
Em um cache miss, a origem externa ainda precisa estar disponível e acessível.
Forçando o laboratório a preencher o cache
O laboratório removeu o cache local do Maven:
rm -rf ~/.m2/repository
Depois compilou:
mvn compile
Isso obrigou o cliente a solicitar novamente as dependências.
Há dois caches diferentes:
- cache local do Maven, em
~/.m2/repository; - cache remoto gerenciado pelo Artifact Registry.
Confundir os dois pode gerar interpretações erradas durante troubleshooting.
Task 4 — Virtual Repository
O que é um Virtual Repository
Virtual Repository é um ponto único de acesso para múltiplos upstream repositories do mesmo formato.
No laboratório, ele combinou:
container-dev-java-repo
maven-central-cache
A política foi:
[
{
"id": "private",
"repository": "projects/PROJECT_ID/locations/us-central1/repositories/container-dev-java-repo",
"priority": 100
},
{
"id": "central",
"repository": "projects/PROJECT_ID/locations/us-central1/repositories/maven-central-cache",
"priority": 80
}
]
E o repositório foi criado:
gcloud artifacts repositories create virtual-maven-repo \
--project=${PROJECT_ID} \
--repository-format=maven \
--mode=virtual-repository \
--location=us-central1 \
--description="Virtual Maven Repo" \
--upstream-policy-file=policy.json
Uma única configuração para o cliente
Sem o virtual, o cliente precisaria conhecer vários repositórios:
<repositories>
<repository>privado</repository>
<repository>remoto</repository>
</repositories>
Com o virtual:
<repositories>
<repository>
<id>artifact-registry</id>
<url>
artifactregistry://us-central1-maven.pkg.dev/PROJECT_ID/virtual-maven-repo
</url>
</repository>
</repositories>
Isso simplifica:
- configuração;
- governança;
- mudança de upstream;
- aplicação de prioridade;
- onboarding de equipes;
- migração de fontes.
O virtual armazena pacotes?
Não diretamente.
Ele funciona como uma camada de resolução.
O conteúdo continua nos upstreams:
pacote privado
→ Standard Repository
pacote público em cache
→ Remote Repository
Virtual Repository
→ interface e política de roteamento
Dependency confusion
O ataque
Imagine que uma empresa usa internamente:
com.iisatech:security-core:1.4.0
O pacote existe apenas no repositório privado.
Se o cliente estiver configurado para consultar fontes privadas e públicas sem uma precedência confiável, um atacante pode tentar publicar em uma origem pública um pacote com coordenadas ou versão capazes de ser escolhidas pelo resolvedor.
O risco aumenta quando:
- ferramentas consultam múltiplos registries;
- a ordem não é controlada;
- versões públicas parecem mais recentes;
- nomes internos vazam;
- clientes acessam registries públicos diretamente;
- políticas variam entre equipes.
Como o virtual ajuda
O laboratório atribuiu:
private priority: 100
central priority: 80
Quando o mesmo artefato pode ser resolvido por mais de um upstream, a prioridade controla qual origem deve prevalecer.
A prioridade maior do repositório privado reduz o risco de o pacote público competir com o pacote interno.
O que a prioridade não resolve sozinha
Virtual Repository é uma camada importante, mas não substitui todas as medidas.
Ainda é necessário:
- controlar quem publica no Standard Repository;
- impedir clientes de consultar Maven Central diretamente;
- reservar namespaces internos;
- usar versões bem definidas;
- revisar parent POMs e plugins;
- fixar versões;
- proteger o
pom.xml; - auditar mudanças de upstream;
- aplicar IAM;
- monitorar dependências;
- validar provenance quando disponível.
Virtual Repository
≠ proteção completa da supply chain
Arquitetura final do laboratório
Automatizando o laboratório
Depois de entender o fluxo manual, construí um script Bash que:
- detecta
PROJECT_IDePROJECT_NUMBER; - habilita a API;
- clona o projeto Java;
- cria os três repositórios;
- gera a política de upstreams;
- modifica o
pom.xml; - cria
.mvn/extensions.xml; - publica o pacote privado;
- limpa o cache local;
- compila pelo Remote Repository;
- recria o cache para demonstrar o Virtual Repository;
- mostra os pacotes armazenados;
- pausa nos pontos de
Check my progress; - imprime explicações durante a execução.
O script também gera arquivos de estudo:
pom.xml.lab-original
standard-repository-settings.txt
remote-repository-settings.txt
virtual-repository-settings.txt
effective-pom-standard.xml
policy.json
Além do laboratório
O laboratório demonstra os três modos, mas uma arquitetura de produção exige decisões adicionais.
1. Separar publicação de consumo
Desenvolvedores e pipelines que publicam pacotes precisam de escrita.
Aplicações consumidoras normalmente precisam apenas de leitura.
publisher
→ roles/artifactregistry.writer
consumer
→ roles/artifactregistry.reader
Não daria permissão de escrita para todos os consumidores.
2. IAM no nível do repositório
Em vez de conceder acesso amplo no projeto, eu usaria permissões específicas por repositório quando possível.
Exemplo:
team-platform
→ writer em platform-snapshots
release-pipeline
→ writer em platform-releases
application-teams
→ reader no virtual repository
3. Acesso aos upstreams do virtual
Quando repositórios virtuais e upstreams estão em projetos diferentes, o agente de serviço do Artifact Registry do projeto virtual precisa ter acesso aos repositórios upstream.
Isso deve ser planejado explicitamente em uma arquitetura cross-project.
4. Separar projetos de desenvolvimento e runtime
Uma arquitetura madura pode usar:
artifact-platform-project
application-build-project
production-runtime-project
O projeto de Artifact Registry torna-se uma plataforma compartilhada.
5. Releases imutáveis
Um release publicado não deveria mudar silenciosamente.
Eu adotaria:
- versões semânticas;
- proibição de sobrescrita;
- promoção por versão;
- auditoria;
- retenção;
- assinatura ou provenance;
- pipeline exclusivo de release.
Snapshots possuem outro ciclo de vida e não deveriam compartilhar as mesmas garantias de releases.
6. Promotion, não rebuild
Para avançar entre estágios, eu evitaria reconstruir um pacote.
O ideal é promover o mesmo artefato validado:
snapshot aprovado
→ release
ou:
quarantine
→ trusted
A identidade do binário precisa permanecer estável.
7. Cleanup policies
Repositórios acumulam:
- snapshots;
- versões antigas;
- metadados;
- artefatos abandonados;
- pacotes de branches temporárias.
Políticas de limpeza ajudam a controlar retenção e custos.
Exemplos:
- manter os últimos 20 snapshots;
- remover versões sem download há determinado tempo;
- preservar releases marcados;
- manter versões usadas em produção;
- remover artefatos de feature branches expiradas.
As políticas precisam considerar recuperação e auditoria.
8. Remote cache não deve ser tratado como backup
O cache remoto é uma otimização e uma camada de controle.
Eu não o trataria como única estratégia de preservação de dependências críticas.
Para componentes essenciais, avaliaria:
- cópia explícita para um Standard Repository;
- mirror aprovado;
- processo de vendor;
- retenção controlada;
- reconstrução reprodutível;
- inventário de dependências.
9. Falhas do upstream
Em um cache miss, o Remote Repository depende do upstream.
Uma indisponibilidade pode afetar um build que solicita uma versão nunca armazenada.
Uma estratégia de resiliência pode incluir:
- prefetch de dependências;
- warm-up do cache;
- builds periódicos;
- mirror interno;
- pin de versões;
- bloqueio de versões dinâmicas;
- validação do conteúdo necessário antes de uma janela crítica.
10. Metadados mutáveis
Arquivos como maven-metadata.xml podem ser atualizados.
O comportamento de cache de metadados é diferente do comportamento de artefatos versionados.
Isso importa especialmente para:
- snapshots;
- ranges de versão;
- plugins;
- versões dinâmicas.
Para builds reprodutíveis, eu evitaria depender de ranges como:
<version>[1.0,2.0)</version>
11. Bloquear acesso direto ao público
O virtual só reduz dependency confusion se os clientes realmente o utilizarem.
Se uma aplicação ainda puder consultar diretamente o Maven Central, a política central pode ser ignorada.
Eu controlaria:
- configuração Maven corporativa;
settings.xml;- egress de rede;
- revisão do
pom.xml; - políticas de CI;
- proxies permitidos;
- Private Pools;
- VPC Service Controls quando aplicável.
12. Namespaces internos
Reservaria coordenadas internas previsíveis:
com.iisatech.*
org.amar.*
br.com.rmcare.*
Além disso:
- verificaria conflitos públicos;
- controlaria criação de novos grupos;
- documentaria ownership;
- impediria publicação não autorizada;
- monitoraria nomes internos expostos.
13. Parent POM corporativo
Uma organização pode distribuir um Parent POM que centraliza:
- versões de plugins;
- Java target;
- políticas de build;
- repositórios;
- análise estática;
- encoding;
- testes;
- SBOM;
- dependency management.
Esse parent também se torna um artefato crítico da supply chain.
Precisa de:
- versionamento;
- revisão;
- proteção;
- releases imutáveis;
- fallback operacional.
14. Plugin repositories
O Maven diferencia dependências de aplicação e plugins de build.
A arquitetura precisa considerar:
<pluginRepositories>
Um build pode continuar consultando origens externas por meio de plugins, mesmo que <repositories> esteja controlado.
Política de dependências precisa abranger os dois caminhos.
15. Service accounts em CI/CD
No Cloud Build, GitHub Actions ou outro sistema, eu não usaria credenciais pessoais.
Usaria identidade de workload:
- service account dedicada;
- Workload Identity Federation para CI externo;
- roles mínimas;
- tokens temporários;
- nenhuma chave JSON persistente.
16. Criptografia
Artifact Registry usa criptografia gerenciada pelo Google por padrão.
Ambientes com requisitos específicos podem usar CMEK.
Nesse caso, o desenho precisa considerar:
- projeto da chave;
- região compatível;
- IAM no KMS;
- rotação;
- disponibilidade;
- impacto de desabilitar a chave;
- política da organização.
17. Localização dos repositórios
A região deve ser escolhida considerando:
- localização dos builds;
- consumidores;
- runtime;
- requisitos de residência;
- latência;
- transferência;
- disaster recovery;
- organização por ambiente.
O modo e a localização não podem ser alterados depois da criação.
Migrar exige criar outro repositório e mover os artefatos.
18. Observabilidade e auditoria
Eu monitoraria:
- criação e exclusão de repositórios;
- mudanças de IAM;
- uploads;
- downloads;
- falhas de resolução;
- alterações de upstream;
- mudanças de prioridade;
- pacotes nunca usados;
- versões antigas;
- aumento inesperado de downloads externos.
Cloud Audit Logs ajuda a investigar operações administrativas e de acesso conforme a configuração aplicável.
19. Vulnerabilidades em pacotes Java
Gerenciar origem e precedência não significa que o pacote é seguro.
Ainda precisamos de:
- Software Composition Analysis;
- SBOM;
- CVE scanning;
- análise de licenças;
- provenance;
- política de aprovação;
- atualização de dependências.
O Virtual Repository decide de onde resolver.
Ele não decide sozinho se o pacote deveria ser usado.
20. Assinatura e provenance
Para pacotes sensíveis, eu conectaria:
build confiável
→ testes
→ SBOM
→ provenance
→ publicação no Standard Repository
→ consumo controlado
Isso permite verificar não apenas a origem do repositório, mas também como o artefato foi produzido.
21. Dependency locking
Maven não possui lockfile nativo equivalente a alguns ecossistemas.
Por isso, eu reforçaria:
- versões explícitas;
dependencyManagement;- Maven Enforcer Plugin;
- banimento de snapshots em releases;
- banimento de ranges;
- verificação de checksums;
- revisão de atualizações automáticas;
- ferramentas de atualização controlada.
22. O próprio Maven Wagon é uma dependência
A extensão de autenticação também faz parte da supply chain.
Eu evitaria usar uma versão flutuante.
Também avaliaria:
- atualização periódica;
- checksum;
- origem;
- release notes;
- compatibilidade;
- inclusão no inventário de dependências.
Arquitetura recomendada para produção
Como aplicaria em ambientes reais
Uma plataforma compartilhada de pacotes poderia armazenar:
- SDKs internos;
- clientes de API;
- módulos de autenticação;
- componentes de observabilidade;
- contratos compartilhados;
- bibliotecas de integração.
Estrutura possível:
platform-java-releases
platform-java-snapshots
maven-central-cache
platform-maven
As aplicações consumiriam apenas:
platform-maven
Plataformas institucionais
Em uma plataforma institucional, pacotes internos poderiam representar:
- modelos de projetos;
- auditoria;
- autorização;
- integrações institucionais;
- componentes de relatórios;
- clientes de serviços governamentais.
O virtual reduziria diferenças de configuração entre módulos e equipes.
Sistemas com dados sensíveis
Em uma plataforma de saúde, eu usaria o registry para controlar:
- bibliotecas de segurança;
- observabilidade;
- integração clínica;
- validações;
- clientes internos;
- contratos entre serviços.
Além de acesso restrito, seria necessário inventário, scanning e processos de atualização.
Google Cloud e AWS: equivalências úteis
| Capacidade | Google Cloud | AWS |
|---|---|---|
| Pacotes privados | Artifact Registry Standard | AWS CodeArtifact |
| Proxy de Maven Central | Artifact Registry Remote | CodeArtifact upstream externo |
| Agregação de origens | Artifact Registry Virtual | Domínio/repositórios com upstreams |
| IAM | Google Cloud IAM | AWS IAM |
| Criptografia gerenciada | Google-managed encryption / CMEK | AWS KMS |
| Publicação Maven | Maven Wagon + mvn deploy |
Maven settings + CodeArtifact auth |
| Cache de terceiros | Remote Repository | External connection/upstream |
| Auditoria | Cloud Audit Logs | CloudTrail |
Os modelos não são idênticos, mas resolvem problemas arquiteturais semelhantes.
Custos e impacto operacional
Uma arquitetura real precisa considerar:
- armazenamento de pacotes privados;
- armazenamento do cache remoto;
- tráfego;
- operações;
- retenção;
- regiões;
- logs;
- KMS quando CMEK é usado;
- custo de manutenção da plataforma.
O cache reduz downloads externos repetidos, mas também acumula conteúdo.
Cleanup policies e visibilidade de uso são necessárias para evitar crescimento indefinido.
Erros e pontos de atenção do laboratório
O título do lab
O nome menciona containers, mas as tarefas são focadas em repositórios Maven.
A conexão com containers aparece quando esses pacotes alimentam builds de aplicações e imagens.
pom.xml sensível à estrutura
As seções precisam ficar dentro de <project>.
XML inválido impede o Maven de carregar o projeto.
IDs únicos
Cada entrada em <repositories> precisa de um id coerente.
O laboratório altera o repositório remoto para:
<id>central</id>
Isso substitui a origem central configurada pelo Super POM do Maven.
Cache local escondendo o resultado
Se ~/.m2/repository já possui as dependências, Maven pode não acessar o Remote Repository.
Por isso o laboratório remove o cache local.
Extensão carregada tarde demais
Parent POMs podem ser resolvidos antes de extensões declaradas apenas no pom.xml.
O arquivo .mvn/extensions.xml evita esse problema.
Recriação do Remote Repository
O laboratório exclui e recria o cache remoto para demonstrar que o acesso pelo Virtual Repository volta a preenchê-lo.
Prioridades
Quanto maior o número, maior a prioridade do upstream na política do virtual.
Versão do pacote
Executar mvn deploy novamente com a mesma versão de release pode falhar dependendo da política e do estado do repositório.
Versionamento faz parte da operação.
O que o laboratório não explicou
O laboratório não aprofunda:
- IAM cross-project;
- agente de serviço do virtual;
- separação de releases e snapshots;
- políticas de limpeza;
- retenção;
- CMEK;
- organização por equipes;
- promoção de pacotes;
- parent POM corporativo;
- plugin repositories;
- Workload Identity Federation;
- SBOM;
- scanning de bibliotecas;
- provenance;
- exceções;
- VPC Service Controls;
- disaster recovery;
- indisponibilidade do upstream;
- prefetch de dependências;
- observabilidade;
- política de namespaces;
- enforcement para impedir acesso direto ao Maven Central.
Esses pontos transformam uma demonstração em uma plataforma de dependências.
Como um arquiteto pensa
Antes de criar os repositórios, eu responderia:
-
Quais pacotes são privados?
Quem é o owner e quem pode publicar? -
Snapshots e releases devem ser separados?
Quais políticas de retenção e imutabilidade cada um terá? -
Quais upstreams externos são permitidos?
Maven Central, mirrors internos ou registries de parceiros? -
Qual precedência será aplicada?
Como impedir dependency confusion? -
Os clientes podem acessar a internet diretamente?
Como evitar bypass do virtual? -
Qual é a identidade dos publishers?
Desenvolvedor, Cloud Build ou pipeline de release? -
Como os artefatos são promovidos?
O mesmo binário chega a produção? -
Como dependências vulneráveis são bloqueadas?
Qual ferramenta e qual política? -
Como responder a indisponibilidade externa?
Cache, mirror, prefetch ou vendor? -
Como medir o serviço?
Cache hit, falhas, downloads, armazenamento e pacotes sem uso.
A topologia de repositórios deve refletir o modelo de confiança da organização.
Principais conceitos utilizados neste artigo.
Serviço gerenciado do Google Cloud para armazenar e distribuir artefatos de software.
Repositório que recebe uploads e publicações diretas de artefatos privados.
Proxy com cache para uma origem upstream externa ou outro repositório compatível.
Ponto único de acesso que combina múltiplos upstream repositories.
Repositório consultado por um Remote ou Virtual Repository.
Repositório público amplamente utilizado pelo ecossistema Java.
Camada de transporte usada pelo Maven para interagir com diferentes protocolos e repositórios.
Seção do POM que define destinos de publicação.
Seção do POM que define origens para resolução de dependências.
POM herdado que centraliza configurações e dependency management.
Ataque em que um pacote público conflitante é escolhido no lugar de uma dependência privada esperada.
Quando o artefato solicitado já está armazenado no Remote Repository.
Quando o Remote Repository precisa consultar o upstream.
Versão de desenvolvimento que pode evoluir durante o ciclo.
Versão publicada como artefato estável e identificável.
Evidência verificável sobre como e onde um artefato foi produzido.
Lições aprendidas
- Dependências fazem parte da software supply chain.
- Standard, Remote e Virtual resolvem responsabilidades diferentes.
- Publicação e resolução usam seções distintas do POM.
- Maven Wagon conecta autenticação e transporte ao Artifact Registry.
.mvn/extensions.xmlé importante para resolução antecipada.- Remote Repository funciona como proxy e cache, não como cópia completa.
- Cache local e cache remoto são camadas diferentes.
- Virtual Repository simplifica o cliente e centraliza precedência.
- Priorizar pacotes privados ajuda a reduzir dependency confusion.
- Um registry seguro ainda precisa de IAM, scanning, provenance e governança.
Como isso ajuda na formação em Cloud Engineering
O laboratório reforça conhecimentos importantes para Cloud, DevOps, DevSecOps e Platform Engineering:
- Artifact Registry;
- Maven;
- repositórios de pacotes;
- IAM;
- autenticação;
- gerenciamento de dependências;
- caching;
- segurança de supply chain;
- dependency confusion;
- automação;
- arquitetura cross-project;
- governança de artefatos.
Para Associate Cloud Engineer, reforça criação e operação de recursos, IAM e uso da CLI.
Para Professional Cloud DevOps Engineer e Professional Cloud Security Engineer, aproxima o aprendizado de software supply chain, platform engineering e controles de entrega.
Conclusão
O laboratório começou com um repositório vazio e terminou com uma arquitetura de dependências em três camadas.
Construímos:
Standard
→ pacotes privados
Remote
→ cache controlado do Maven Central
Virtual
→ uma interface única com prioridade
O aprendizado principal não foi apenas executar:
mvn deploy
Foi entender que o local de onde uma dependência é resolvida faz parte do modelo de segurança.
Ao colocar o pacote privado com prioridade maior que o repositório público, a arquitetura reduz risco de confusão de dependências.
Ao adicionar um cache remoto, reduz dependência direta e repetitiva do Maven Central.
Ao expor uma única URL virtual, simplifica a configuração e centraliza a política.
O resultado é um modelo mais próximo de uma plataforma interna de artefatos:
publicar de forma controlada, consumir por uma interface governada e tratar dependências como componentes críticos da supply chain.
Próximo capítulo
No próximo capítulo da Google Cloud Master Journey 2026, a jornada continuará conectando:
- builds seguros;
- dependências controladas;
- scanning;
- provenance;
- attestations;
- autorização de deploy;
- segurança de ponta a ponta.
Depois de proteger build, artefato e dependência, o próximo passo é unir essas camadas em uma política completa de entrega segura.
Referências oficiais consultadas
- Google Cloud — Artifact Registry repository overview
- Google Cloud — Create standard repositories
- Google Cloud — Remote repositories overview
- Google Cloud — Create remote repositories
- Google Cloud — Virtual repositories overview
- Google Cloud — Create virtual repositories
- Google Cloud — Configure authentication for Maven and Gradle
- Google Cloud — Manage Java packages
- Google Cloud — Store Java packages in Artifact Registry
- Google Cloud — Artifact Registry access control with IAM
- Google Cloud — Artifact Registry roles and permissions
- Google Cloud — Cleanup policy overview
- Google Cloud — Configure cleanup policies
- Apache Maven — POM reference
- Apache Maven — Guide to using extensions
Comentários
Em breveAs respostas da comunidade chegam em breve.
Leia também
- Sensitive Data Protection no Google Cloud: descubra, inspecione e desidentifique dados no Cloud StorageGCP23 min de leitura19 de jul. de 2026
- Secure Builds com Cloud Build: bloqueando imagens vulneraveis antes do Artifact RegistryGCP25 min de leitura18 de jul. de 2026
- Secure Software Supply Chain no Google Cloud: Binary Authorization, Cloud KMS e GKE na praticaGCP24 min de leitura18 de jul. de 2026