Tipo de conteúdo: Laboratório prático
Nível: Intermediário
Tecnologias: Azure Virtual Network Manager, Azure Virtual Network, Azure Policy, Security Admin Rules, Azure Portal, Run Command e GitHub
Repositório: https://github.com/leomcoco/azure-virtual-network-manager-enterprise-lab
Artigo relacionado: Azure Virtual Network Manager na prática: conectividade e segurança de redes em escala enterprise
Tempo estimado de leitura: 6 minutos
Tempo estimado de laboratório: 1h30 a 2h
Este artigo dá continuidade ao laboratório anterior de Azure Virtual Network Manager. No primeiro artigo, o foco foi a criação da base de governança de conectividade e segurança. Neste, o objetivo é validar a solução na prática, usando VMs, testes de tráfego real, associação dinâmica de VNets e Security Admin Rules.
Resumo prático
No artigo anterior, criei a base de um laboratório com Azure Virtual Network Manager: network group, conectividade hub-spoke, associação dinâmica com Azure Policy e uma baseline de segurança com Security Admin Rules.
Agora a proposta é validar o comportamento da solução com testes mais próximos da prática.
A pergunta principal é simples:
quando uma nova VNet entra no ambiente, a governança realmente funciona?
Para responder, o laboratório cria uma nova spoke, adiciona VMs Linux sem IP público e executa testes de conectividade usando Run Command pela console da VM no Azure Portal.
A ideia é validar comportamento, não apenas configuração.
Os testes respondem quatro perguntas:
- uma nova VNet entra automaticamente no modelo governado?
- o hub consegue acessar uma spoke com tráfego real?
- as spokes continuam isoladas quando direct connectivity não está habilitado?
- uma regra central bloqueia uma porta administrativa de alto risco?
Arquitetura do teste
A arquitetura parte do laboratório anterior e adiciona uma nova spoke dinâmica com VMs para validação.
Azure Virtual Network Manager
│
├── Network Group: ng-spokes-lab
│ ├── vnet-spoke-app-001
│ ├── vnet-spoke-data-001
│ └── vnet-spoke-dynamic-001
│
├── Connectivity Configuration
│ └── Hub-Spoke
│
└── Security Admin Configuration
└── deny-rdp-inbound-to-spokes
Hub:
└── vnet-hub-shared-001
└── vm-hub-test-001
Spoke existente:
└── vnet-spoke-app-001
└── vm-spoke-app-test-001
Spoke dinâmica:
└── vnet-spoke-dynamic-001
└── vm-spoke-dynamic-test-001

Arquitetura usada para testar conectividade, segmentação e segurança com Azure Virtual Network Manager.
Como os testes serão executados
Os recursos do laboratório são criados por scripts no GitHub.
Os testes de conectividade, porém, serão demonstrados no artigo usando o Run Command pela console da VM:
Azure Portal > Virtual Machines > VM > Operations > Run command > RunShellScript
Esse formato facilita a evidência visual, porque o print mostra:
- a VM usada no teste;
- o comando executado;
- a saída do teste;
- que não foi necessário IP público;
- que não foi necessário abrir SSH para internet.
O GitHub continua sendo a base reproduzível do laboratório. O portal entra como evidência visual do comportamento.
Matriz de testes
| Teste | Resultado esperado | O que valida |
|---|---|---|
| VNet com tags corretas | Entra no modelo governado | Associação dinâmica |
| VNet sem tags esperadas | Fica fora do network group | Controle por critério |
| Hub acessa Spoke na porta 8080 | Sucesso | Conectividade hub-spoke |
| Spoke acessa outra Spoke na porta 8080 | Falha | Segmentação |
| Hub acessa Spoke na porta 3389 | Falha | Security Admin Rule |
| NSG permite 3389, mas AVNM nega | Falha | Guardrail central prevalece |
O que este laboratório não está testando
Este laboratório não transforma o Azure Virtual Network Manager em firewall.
A porta 3389 é usada como exemplo de porta administrativa de alto risco. O objetivo é validar uma baseline central de segurança aplicada com Security Admin Rules.
Para inspeção de tráfego, regras de aplicação, FQDN filtering, Threat Intelligence, SNAT, DNAT ou IDPS, o componente adequado continua sendo Azure Firewall, Azure Firewall Premium, NVA ou solução equivalente.
Aqui o foco é governança central de conectividade e segurança em escala.
Teste 1 — Nova VNet entrando no modelo
O primeiro teste cria uma nova VNet com as tags esperadas pela política de associação dinâmica:
vnet-spoke-dynamic-001
environment = lab
workload = avnm-demo
role = spoke
Resultado esperado:
A VNet entra no network group governado pelo Azure Virtual Network Manager.
Esse teste simula crescimento real do ambiente. A governança não pode depender apenas das redes criadas no primeiro deploy.

VNet criada com as tags usadas pela política de associação dinâmica.

Nova VNet associada ao modelo governado pelo AVNM.
Teste 2 — VNet fora do padrão
O segundo teste cria uma VNet sem a classificação necessária:
vnet-outofpolicy-001
Sem a tag:
role = spoke
Resultado esperado:
A VNet não entra no network group governado.
Esse teste é importante porque prova que a governança tem critério. Ela não deve capturar qualquer rede automaticamente.

VNet criada sem a classificação necessária para entrar no modelo governado.
Teste 3 — VMs sem IP público
Para validar tráfego real, o laboratório usa três VMs Linux pequenas:
| VM | VNet | Função |
|---|---|---|
vm-hub-test-001 | vnet-hub-shared-001 | Origem dos testes a partir do hub |
vm-spoke-app-test-001 | vnet-spoke-app-001 | Spoke existente |
vm-spoke-dynamic-test-001 | vnet-spoke-dynamic-001 | Nova spoke dinâmica |
As VMs não precisam de IP público. Os testes serão executados pelo Run Command no portal.

VMs Linux criadas sem IP público para testes de conectividade e segurança.
Teste 4 — Preparar os serviços de teste na VM da spoke dinâmica
Antes de testar conectividade e bloqueio, preparei dois serviços simples dentro da VM vm-spoke-dynamic-test-001.
A execução foi feita pelo Azure Portal:
Virtual Machines > vm-spoke-dynamic-test-001 > Run command > RunShellScript
Teste 4 — Subir serviço na porta 8080
Este teste inicia um serviço HTTP simples na VM da spoke dinâmica.
Acesse:
Azure Portal > Virtual Machines > vm-spoke-dynamic-test-001 > Run command > RunShellScript
Execute:
nohup python3 -m http.server 8080 --bind 0.0.0.0 >/tmp/http-8080.log 2>&1 &
nohup python3 -m http.server 3389 --bind 0.0.0.0 >/tmp/http-3389.log 2>&1 &
ss -ltn | grep -E ":8080|:3389" || true
A porta 8080 será usada para validar a conectividade permitida entre hub e spoke.
A porta 3389 será usada como exemplo de porta administrativa de alto risco, apenas para validar o bloqueio TCP pela Security Admin Rule. Como a VM é Linux, este teste não valida RDP real.
Resultado esperado:
LISTEN ... 0.0.0.0:8080
LISTEN ... 0.0.0.0:3389
Esse resultado confirma que os serviços estão ativos dentro da VM antes dos testes de conectividade e segurança.

Serviço HTTP iniciado dentro da VM da spoke dinâmica usando Run Command.
Teste 5 — Hub acessando Spoke dinâmica na porta 8080
Agora o teste parte da VM Hub para validar a conectividade aplicada pelo Azure Virtual Network Manager com tráfego real entre as VNets.
Antes de executar o teste a partir do hub, foi iniciado um serviço HTTP simples na VM vm-spoke-dynamic-test-001, escutando na porta 8080.
No laboratório executado, o IP privado da VM da spoke dinâmica foi:
10.40.1.4
Acesse no Azure Portal:
Virtual Machines > vm-hub-test-001 > Run command > RunShellScript
Execute o comando abaixo no Run Command da VM vm-hub-test-001:
python3 - <<'PYTHON'
import socket
host = "10.40.1.4"
port = 8080
try:
socket.create_connection((host, port), timeout=5).close()
print(f"PASS: {host}:{port} reachable from hub VM")
except Exception as e:
print(f"FAIL: {host}:{port} not reachable from hub VM: {e}")
raise SystemExit(1)
PYTHON
Resultado obtido:
PASS: 10.40.1.4:8080 reachable from hub VM
Esse teste valida que a VM no hub consegue estabelecer uma conexão TCP com a VM da spoke dinâmica na porta 8080.
Na prática, essa evidência confirma que a conectividade Hub-Spoke aplicada pelo Azure Virtual Network Manager foi materializada corretamente por meio dos peerings gerenciados ANM_*.

Teste bem-sucedido de conectividade entre a VM Hub e a VM da spoke dinâmica na porta 8080.
Teste 6 — Spoke-to-spoke sem direct connectivity
Agora o teste parte da VM localizada em uma spoke existente.
Acesse no Azure Portal:
Virtual Machines > vm-spoke-app-test-001 > Run command > RunShellScript
Neste teste, use o IP privado real da VM vm-spoke-dynamic-test-001.
No laboratório executado, o IP privado da VM da spoke dinâmica foi:
10.40.1.4
Execute o comando abaixo no Run Command da VM vm-spoke-app-test-001:
python3 - <<'PYTHON'
import socket
host = "10.40.1.4"
port = 8080
try:
socket.create_connection((host, port), timeout=5).close()
print(f"FAIL: {host}:{port} reachable from spoke VM. Direct spoke-to-spoke connectivity may be enabled.")
raise SystemExit(1)
except Exception as e:
print(f"PASS: {host}:{port} not reachable from spoke VM, as expected")
PYTHON
Resultado esperado:
PASS: 10.40.1.4:8080 not reachable from spoke VM, as expected
Esse resultado é esperado porque o desenho atual usa topologia Hub-Spoke, sem direct connectivity entre spokes.
Neste caso, a falha de comunicação é uma evidência positiva: o Azure Virtual Network Manager respeita o modelo definido e não transforma automaticamente as spokes em uma malha.

Teste mostrando que duas spokes não se comunicam diretamente quando direct connectivity não está habilitado.
Teste 7 — Bloqueio da porta 3389
A porta 3389 será usada como exemplo de porta administrativa de alto risco.
A VM do laboratório é Linux. Portanto, este teste não valida RDP real. O objetivo é validar o bloqueio de tráfego TCP na porta 3389.
Primeiro, inicie um serviço de teste na porta 3389 dentro da VM da spoke dinâmica.
Acesse no Azure Portal:
Virtual Machines > vm-spoke-dynamic-test-001 > Run command > RunShellScript
Execute:
nohup python3 -m http.server 3389 --bind 0.0.0.0 >/tmp/http-3389.log 2>&1 &
ss -ltn | grep -E ':3389\s' || true
Resultado esperado:
Enable succeeded:
[stdout]
[stderr]
Esse primeiro passo confirma apenas que existe um serviço escutando na porta 3389 dentro da VM vm-spoke-dynamic-test-001.
Agora execute o teste a partir da VM Hub.
Acesse no Azure Portal:
Virtual Machines > vm-hub-test-001 > Run command > RunShellScript
Execute:
python3 - <<'PYTHON'
import socket
host = "10.40.1.4"
port = 3389
try:
socket.create_connection((host, port), timeout=5).close()
print(f"FAIL: {host}:{port} reachable from hub VM. Port 3389 was not blocked.")
raise SystemExit(1)
except Exception as e:
print(f"PASS: {host}:{port} blocked or timed out from hub VM, as expected")
PYTHON
Resultado esperado:
PASS: 10.40.1.4:3389 blocked or timed out from hub VM, as expected
Esse teste mostra que a porta 3389 não está acessível a partir da VM Hub. A confirmação mais forte de que o bloqueio vem da governança central será feita no próximo teste, comparando o resultado com a regra local do NSG.

Teste mostrando bloqueio de tráfego TCP na porta 3389 para a VM da spoke dinâmica.
Teste 8 — NSG permite, mas AVNM mantém o bloqueio
Este é um dos testes mais importantes do laboratório.
A ideia é validar a diferença entre uma regra local de NSG e uma regra administrativa central aplicada pelo Azure Virtual Network Manager.
Neste cenário:
- o NSG local permite tráfego na porta
3389; - a Security Admin Rule do AVNM bloqueia a porta
3389; - o teste de conectividade a partir da VM Hub continua falhando.
No terminal com Azure CLI, valide a regra local no NSG da VM da spoke dinâmica:
az network nsg rule list \
--resource-group rg-avnm-lab \
--nsg-name nsg-spoke-dynamic-test-001 \
--query "[?destinationPortRange=='3389'].{name:name,priority:priority,access:access,direction:direction,source:sourceAddressPrefix,destinationPort:destinationPortRange}" \
--output table
Resultado esperado:
Name Priority Access Direction Source DestinationPort
------------------------------ ---------- -------- ----------- -------------- -----------------
Allow-3389-From-VirtualNetwork 110 Allow Inbound VirtualNetwork 3389
Agora repita o teste a partir da VM Hub.
Acesse no Azure Portal:
Virtual Machines > vm-hub-test-001 > Run command > RunShellScript
Execute:
python3 - <<'PYTHON'
import socket
host = "10.40.1.4"
port = 3389
try:
socket.create_connection((host, port), timeout=5).close()
print(f"FAIL: {host}:{port} reachable from hub VM. The central baseline did not block the traffic.")
raise SystemExit(1)
except Exception as e:
print(f"PASS: {host}:{port} still blocked even with NSG allow rule, as expected")
PYTHON
Resultado esperado:
PASS: 10.40.1.4:3389 still blocked even with NSG allow rule, as expected
Esse teste evidencia a função das Security Admin Rules como baseline central de segurança.
O NSG continua sendo importante para o controle local da subnet ou da interface de rede. O Azure Firewall continua sendo importante para inspeção, controle centralizado e cenários avançados de tráfego. Mas a Security Admin Rule do AVNM ajuda a garantir que uma regra local mais permissiva não enfraqueça uma restrição administrativa definida para o ambiente.

Regra local de NSG permitindo tráfego TCP na porta 3389.

Mesmo com regra local permitindo 3389, a Security Admin Rule do AVNM mantém o bloqueio.
Teste 9 — Configurações efetivas aplicadas à VNet
Por fim, valide o plano de controle.
Este teste confirma quais configurações do Azure Virtual Network Manager estão efetivamente aplicadas à VNet vnet-spoke-dynamic-001.
No terminal com Azure CLI, execute:
az network manager list-effective-connectivity-config \
--resource-group rg-avnm-lab \
--virtual-network-name vnet-spoke-dynamic-001 \
--query "value[].{topology:connectivityTopology,configuration:id,hub:hubs[0].resourceId}" \
--output jsonc
Resultado esperado:
"topology": "HubAndSpoke"
Depois, valide a regra administrativa de segurança efetiva:
az network manager list-effective-security-admin-rule \
--resource-group rg-avnm-lab \
--virtual-network-name vnet-spoke-dynamic-001 \
--query "value[].{name:name,access:access,direction:direction,protocol:protocol,destinationPortRanges:destinationPortRanges,description:description}" \
--output jsonc
Resultado esperado:
[
{
"access": "Deny",
"description": "Deny inbound RDP to lab spokes",
"destinationPortRanges": [
"3389"
],
"direction": "Inbound",
"name": null,
"protocol": "Tcp"
}
Essa validação fecha o ciclo do laboratório: além dos testes de tráfego, o plano de controle confirma que a VNet dinâmica recebeu a configuração Hub-Spoke e a regra administrativa de segurança definida no AVNM.
Opcionalmente, valide também a VNet fora do padrão:
az network manager list-effective-connectivity-config \
--resource-group rg-avnm-lab \
--virtual-network-name vnet-outofpolicy-001 \
--output jsonc
Resultado esperado:
{
"skipToken": "",
"value": []
}
Esse resultado mostra que a VNet fora do padrão não recebeu a mesma configuração do AVNM, pois não atende aos critérios de associação ao network group.

Validação das configurações efetivas de conectividade e segurança aplicadas à nova VNet.
Artefatos no GitHub
O mesmo repositório do artigo anterior será usado para manter a continuidade do laboratório:
https://github.com/leomcoco/azure-virtual-network-manager-enterprise-lab
Para este cenário, o repositório deve conter uma nova pasta:
scenarios/
└── 02-vm-runtime-tests/
Esse cenário deve incluir:
- scripts separados por etapa;
- README específico;
- matriz de testes;
- resultados esperados;
- cleanup do cenário;
- comandos usados no Run Command;
- orientações para evidências.
O artigo mostra a lógica, os testes e os principais resultados. O GitHub concentra os detalhes operacionais para quem quiser reproduzir.

O que os testes provam
Este laboratório prova quatro pontos.
Primeiro: novas VNets classificadas corretamente podem entrar no modelo governado.
Segundo: a conectividade hub-spoke funciona com tráfego real.
Terceiro: spokes não passam a se comunicar diretamente quando direct connectivity não está habilitado.
Quarto: uma Security Admin Rule consegue bloquear uma porta administrativa de alto risco mesmo diante de tentativa de liberação local.
Esse é o valor prático do AVNM: transformar governança de rede em algo testável.
Cuidados e custos
Antes de executar:
- use uma subscription de laboratório;
- mantenha as VMs sem IP público;
- use SKUs pequenas;
- execute cleanup ao final;
Conclusão
Azure Virtual Network Manager fica mais interessante quando sai da configuração e entra no teste real.
Neste laboratório, a ideia foi validar se a governança continua funcionando conforme o ambiente cresce: uma nova VNet entra no modelo, a conectividade esperada funciona, a comunicação direta entre spokes não acontece por padrão e uma regra central bloqueia tráfego administrativo de alto risco.
Para times de plataforma, segurança e arquitetura, esse tipo de teste é mais útil do que apenas mostrar que o recurso foi criado.
Em ambientes Azure em escala, governança de rede precisa ser reproduzível, testável e evidenciável.
Referências oficiais
Microsoft Learn — What is Azure Virtual Network Manager?
Microsoft Learn — Connectivity configurations in Azure Virtual Network Manager
Microsoft Learn — Security admin rules in Azure Virtual Network Manager
Microsoft Learn — Azure Policy definitions addToNetworkGroup effect
Microsoft Learn — Run scripts in your Linux VM by using action Run Commands


