Liberando agentes de build dinamicamente no firewall do ACR

Mais um post direto das trincheiras. Um de nossos clientes está usando Azure Container Registry com o firewall do registry ativado e por isso não estava conseguindo publicar suas imagens durante o build.

O problema

Isso porque, com o firewall ativado, o Azure Container Registry passa a recusar qualquer conexão direta feita via IP público. A ideia com isso é limitar o acesso ao Registry a uma rede privada virtual, impedindo o acesso através da internet pública.

O problema é que, dessa forma, os agentes do Azure Pipelines obviamente não conseguem mais acessar o Registry. A única maneira de permitir que os agentes façam “push” para o registry é incluindo seus IPs na lista de exclusões (“whitelist”) do firewall.

A solução

Como os IPs dos agentes de pipelines do Azure DevOps são dinâmicos, pré-cadastrar os IPs dos agentes no firewall não seria uma opção. E ainda que a Microsoft publique semanalmente os IPs dos serviços do Azure, ter que fazer essa manutenção (recadastrar todos os IPs semanalmente) seria muito trabalhoso e, ainda por cima, sujeito a erros.

A alternativa que propusemos ao cliente foi liberar os IPs sob demanda, no instante do build. Ou seja, teríamos um pipeline que, em alto nível, faria isto:

Sequência do pipeline listando as quatro etapas - gera imagem do Docker, libera firewall, publica imagem, remove liberação do firewall
Sequência do pipeline listando as quatro etapas - gera imagem do Docker, libera firewall, publica imagem, remove liberação do firewall (clique para ampliar)

Para poder adicionar/remover o agente, precisamos:

  • Pegar o IP público do agente atual; e
  • Usar a Azure CLI para adicionar/remover esse IP.

Eis um exemplo da task Azure CLI obtendo o IP do agente atual (através de uma chamada de DNS usando a ferramenta de linha de comando dig) e então a passando como parâmetro para o az acr network-rule add:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- task: AzureCLI@2
    name: 
    displayName: 'Add agent IP to firewall whitelist'
    inputs:
    azureSubscription: $(azureSubscription)
    scriptType: 'bash'
    scriptLocation: 'inlineScript'
    inlineScript: |
        AGENT_IP="$(dig +short myip.opendns.com @resolver1.opendns.com)"
        
        if [ -z "$(az acr network-rule list --name $(containerRegistry) | grep ${AGENT_IP})"]
        then 
            echo "Adicionando IP '${AGENT_IP}' ao firewall do Azure Container Registry '$(containerRegistry)'"
            
            az acr network-rule add --name $(containerRegistry) --ip-address $AGENT_IP
        else
            echo "Agent já está liberado; ignorando."
        fi

Com isso, você já consegue usar a task do Docker para publicar a imagem no ACR desejado. Depois da publicação, é só remover o IP que acabamos de adicionar:

1
2
3
4
5
6
7
8
9
10
11
12
13
- task: AzureCLI@2
    displayName: 'Remove agent IP from firewall whitelist'
    condition: always()
    inputs:
    azureSubscription: $(azureSubscription)
    scriptType: 'bash'
    scriptLocation: 'inlineScript'
    inlineScript: |
        AGENT_IP="$(dig +short myip.opendns.com @resolver1.opendns.com)"
        
        echo "Removing agent IP '${AGENT_IP}' from Azure Container Registry '$(containerRegistry)' firewall whitelist"

        az acr network-rule remove --name $(containerRegistry) --ip-address $AGENT_IP --only-show-errors --output none

Note que colocamos nesta segunda task condition: always(). Isso é importante, pois queremos que o IP seja removido do firewall em qualquer circunstância, mesmo quando por exemplo ocorrer um erro na publicação. Sem isso, esta tareja não seria executada em caso de erro na publicação e poderíamos acabar com um montão de IPs atulhando o firewall do ACR.

IMPORTANTE: No momento da publicação deste post o recurso de Firewall/VNet do Azure Container Registry ainda estava em preview, portanto pode ser que ele ainda sofra mudanças até o momento de ser finalmente disponibilizado.

Conclusão

O novo recurso de acesso restrito do Azure Container Registry, que oferece acesso exclusivo por VNet e/ou firewall é um importante mecanismo de segurança para seus registries de contêineres. Entretanto, diferentemente de outros serviços do Azure que oferecem uma “checkbox mágica” para liberar a passagem através do firewall para quaisquer serviços do Azure (incluindo o Azure Pipelines), o ACR Firewall ainda não suporta essa exceção automática. Por isso é que precisamos fazer isso em tempo de build, usando a ferramenta de linha de comando do Azure.

Para um exemplo completo de um pipeline fazendo esse processo, dê uma olhada neste gist.

Um abraço,
  Igor



29/04/2020 | Por Igor Abade V. Leite | Em Técnico | Tempo de leitura: 3 mins.

Postagens relacionadas