Confiança do Certificado de Desenvolvimento .NET no Linux
Quando Usar Esta Skill
Use esta skill quando:
- Conexões TLS do Redis falharem com
UntrustedRootouRemoteCertificateNameMismatchno Aspire dotnet dev-certs https --check --trustretornar código de saída 7- Conexões HTTPS localhost falharem com erros de validação de certificado
- Após executar
dotnet dev-certs https --cleane precisar restaurar a confiança - Configurando uma nova máquina de desenvolvimento Linux para desenvolvimento .NET HTTPS
- O dashboard do Aspire ou chamadas gRPC entre serviços falharem com erros TLS
- Atualizando do Aspire < 13.1.0 (que não usava TLS no Redis por padrão)
O Problema
No Windows e macOS, dotnet dev-certs https --trust lida com tudo automaticamente — ele gera o certificado, instala no repositório do usuário e o adiciona ao repositório de confiança do sistema. No Linux, ele não faz quase nada de útil. O comando gera o certificado e o coloca no repositório do usuário, mas:
- Ele não exporta o certificado para o diretório de CAs do sistema
- Ele não executa
update-ca-certificatespara reconstruir o pacote de CAs - Ele não adiciona o certificado aos repositórios de confiança do navegador (NSS/NSSDB)
- A flag
--trusté bem-sucedida silenciosamente, mas o certificado permanece não confiável
Isso significa que aplicações .NET, OpenSSL, curl e navegadores rejeitam o certificado de desenvolvimento — mesmo que dotnet dev-certs https --check informe que ele existe.
Por Que Isso Aparece com Aspire 13.1.0+
Antes do Aspire 13.1.0, as conexões Redis usavam texto simples. A partir do 13.1.0, o Aspire habilita TLS no Redis por padrão. Se seu certificado de desenvolvimento não for confiável no nível do sistema, as conexões Redis falham imediatamente com:
System.Security.Authentication.AuthenticationException:
The remote certificate is invalid because of errors in the certificate chain: UntrustedRoot
Como Funciona a Confiança do Certificado no Linux
Entender a arquitetura evita depuração sem método:
┌─────────────────────────────────────────────────────┐
│ Application (.NET, curl, OpenSSL) │
│ lê: /etc/ssl/certs/ca-certificates.crt │
│ (pacote de CA consolidado) │
└──────────────────────┬──────────────────────────────┘
│ construído por
┌──────────────────────▼──────────────────────────────┐
│ update-ca-certificates │
│ lê de: │
│ /usr/share/ca-certificates/ (CAs da distro) │
│ /usr/local/share/ca-certificates/ (CAs locais) │
│ escreve em: │
│ /etc/ssl/certs/ca-certificates.crt (pacote) │
│ /etc/ssl/certs/*.pem (links simbólicos individuais)│
└─────────────────────────────────────────────────────┘
Insight chave: Colocar um arquivo .crt em /usr/local/share/ca-certificates/ é necessário, mas não suficiente. O pacote consolidado em /etc/ssl/certs/ca-certificates.crt deve ser reconstruído executando update-ca-certificates. As aplicações leem o pacote, não os arquivos individuais.
Procedimento de Diagnóstico de 5 Pontos
Execute estas verificações em ordem. Pare no primeiro FAIL e aplique sua correção antes de continuar.
Verificação 1: Existência do Certificado de Desenvolvimento
dotnet dev-certs https --check
echo "Código de saída: $?"
| Código de Saída | Significado | Ação |
|---|---|---|
| 0 | Certificado existe no repositório do usuário | PASS — continue |
| Diferente de zero | Nenhum cert. de desenvolvimento válido | Execute dotnet dev-certs https |
Verificação 2: Repositório de Confiança do Sistema — Certificado Único, Permissões Corretas
ls -la /usr/local/share/ca-certificates/ | grep -iE 'dotnet|aspnet'
| Resultado | Significado |
|---|---|
Apenas dotnet-dev-cert.crt com -rw-r--r-- (644) | PASS |
Múltiplos arquivos de certificado, permissões erradas ou arquivos aspnet* obsoletos | FAIL |
Arquivos obsoletos comuns de sessões anteriores:
| Arquivo | Problema |
|---|---|
aspnetcore-dev.crt | Frequentemente criado com permissões 0600 (ilegível para update-ca-certificates) |
aspnet/https.crt | Convenção antiga, pode ter uma impressão digital diferente do certificado de desenvolvimento atual |
dotnet-dev-cert.crt com 0600 | Nome correto, mas permissões erradas |
Correção:
# Remova TODOS os arquivos de certificado obsoletos
sudo rm -f /usr/local/share/ca-certificates/aspnetcore-dev.crt
sudo rm -rf /usr/local/share/ca-certificates/aspnet/
# Garanta permissões corretas no certificado de desenvolvimento (se existir)
sudo chmod 644 /usr/local/share/ca-certificates/dotnet-dev-cert.crt
Verificação 3: Inclusão no Pacote de CA
Esta é a verificação que mais comumente falha. O arquivo de certificado existe, mas nunca foi adicionado ao pacote.
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt \
/usr/local/share/ca-certificates/dotnet-dev-cert.crt
| Resultado | Significado |
|---|---|
dotnet-dev-cert.crt: OK | PASS — o certificado está no pacote consolidado |
error 20 at 0 depth lookup: unable to get local issuer certificate | FAIL — o pacote nunca foi reconstruído |
error 2 at 0 depth lookup: unable to get issuer certificate | FAIL — mesmo problema, versão diferente do OpenSSL |
Correção:
sudo update-ca-certificates
# A saída esperada inclui "1 added" ou similar
# Re-verifique
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt \
/usr/local/share/ca-certificates/dotnet-dev-cert.crt
Verificação 4: Substituições de Variáveis de Ambiente
Variáveis de ambiente SSL podem redirecionar as consultas de certificado para longe do pacote do sistema:
echo "SSL_CERT_DIR=${SSL_CERT_DIR:-<não definido>}"
echo "SSL_CERT_FILE=${SSL_CERT_FILE:-<não definido>}"
echo "DOTNET_SSL_CERT_DIR=${DOTNET_SSL_CERT_DIR:-<não definido>}"
echo "DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER=${DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER:-<não definido>}"
| Resultado | Significado |
|---|---|
Todos <não definido> | PASS |
| Qualquer variável definida | FAIL — pode redirecionar consultas de certificado |
Correção: Remova as variáveis problemáticas do seu perfil de shell (~/.bashrc, ~/.zshrc, ~/.profile) e inicie um novo shell.
Verificação 5: Integridade dos Links Simbólicos
Links simbólicos obsoletos de certificados removidos anteriormente podem confundir o OpenSSL:
find /etc/ssl/certs/ -xtype l 2>/dev/null | head -5
| Resultado | Significado |
|---|---|
| Nenhuma saída | PASS |
| Links simbólicos quebrados listados | FAIL |
Correção:
sudo update-ca-certificates --fresh
# Reconstrói TODOS os links simbólicos do zero
Procedimento Completo de Recuperação
Quando várias verificações falharem ou você quiser começar do zero, execute esta sequência completa:
#!/usr/bin/env bash
set -euo pipefail
echo "=== Recuperação da Confiança do Certificado de Desenvolvimento .NET ==="
# Passo 1: Remova TODOS os arquivos de certificado obsoletos
echo "--- Removendo arquivos de certificado obsoletos ---"
sudo rm -f /usr/local/share/ca-certificates/aspnetcore-dev.crt
sudo rm -rf /usr/local/share/ca-certificates/aspnet/
sudo rm -f /usr/local/share/ca-certificates/dotnet-dev-cert.crt
# Passo 2: Limpe e regenere o certificado de desenvolvimento
echo "--- Regenerando o certificado de desenvolvimento ---"
dotnet dev-certs https --clean
dotnet dev-certs https
# Passo 3: Exporte como PEM e instale no repositório de confiança do sistema
echo "--- Instalando no repositório de confiança do sistema ---"
dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.crt --format PEM --no-password
sudo cp /tmp/dotnet-dev-cert.crt /usr/local/share/ca-certificates/dotnet-dev-cert.crt
sudo chmod 644 /usr/local/share/ca-certificates/dotnet-dev-cert.crt
rm /tmp/dotnet-dev-cert.crt
# Passo 4: Reconstrua o pacote de CA (CRÍTICO — etapa mais comumente esquecida)
echo "--- Reconstruindo o pacote de CA ---"
sudo update-ca-certificates
# Passo 5: Verifique
echo "--- Verificando ---"
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt \
/usr/local/share/ca-certificates/dotnet-dev-cert.crt
echo "=== Pronto! Reinicie sua aplicação .NET. ==="
Salve isso como ~/fix-devcert.sh e execute com bash ~/fix-devcert.sh quando necessário.
Notas Específicas por Distribuição
Ubuntu / Debian
O procedimento acima foi escrito para Ubuntu/Debian e funciona como está.
- Diretório de CA:
/usr/local/share/ca-certificates/ - Comando do pacote:
sudo update-ca-certificates - Saída do pacote:
/etc/ssl/certs/ca-certificates.crt - Formato do certificado: PEM com extensão
.crtnecessária
Fedora / RHEL / CentOS
Fedora usa update-ca-trust em vez de update-ca-certificates:
# Exporte o certificado
dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.pem --format PEM --no-password
# Instale no repositório de confiança do Fedora (diretório diferente!)
sudo cp /tmp/dotnet-dev-cert.pem /etc/pki/ca-trust/source/anchors/dotnet-dev-cert.pem
sudo chmod 644 /etc/pki/ca-trust/source/anchors/dotnet-dev-cert.pem
rm /tmp/dotnet-dev-cert.pem
# Reconstrua o pacote de confiança
sudo update-ca-trust
# Verifique
openssl verify /etc/pki/ca-trust/source/anchors/dotnet-dev-cert.pem
Principais diferenças:
| Ubuntu/Debian | Fedora/RHEL | |
|---|---|---|
| Diretório de CA | /usr/local/share/ca-certificates/ | /etc/pki/ca-trust/source/anchors/ |
| Comando de reconstrução | update-ca-certificates | update-ca-trust |
| Caminho do pacote | /etc/ssl/certs/ca-certificates.crt | /etc/pki/tls/certs/ca-bundle.crt |
| Extensão | .crt | .pem (qualquer extensão funciona) |
Arch Linux
Arch usa a mesma abordagem update-ca-trust que o Fedora:
sudo cp /tmp/dotnet-dev-cert.pem /etc/ca-certificates/trust-source/anchors/dotnet-dev-cert.pem
sudo chmod 644 /etc/ca-certificates/trust-source/anchors/dotnet-dev-cert.pem
sudo update-ca-trust
WSL2
WSL2 executa um kernel Linux real com seu próprio repositório de certificados — separado do host Windows. O procedimento padrão Ubuntu/Debian funciona, mas fique atento a:
- Sistema de arquivos compartilhado (
/mnt/c/) — arquivos de certificado no sistema de arquivos Windows têm permissões do Windows que podem não ser 644. Sempre copie para um caminho Linux nativo primeiro. - systemd não está em execução — algumas configurações mais antigas do WSL2 não têm systemd, do qual os hooks do
update-ca-certificatespodem depender. Se o comando travar, tentesudo dpkg-reconfigure ca-certificatescomo alternativa. - Integração com Docker Desktop — Se estiver usando o backend WSL2 do Docker Desktop, os contêineres herdam o pacote de CA da distribuição WSL2. Corrigir a confiança no WSL2 também a corrige para os contêineres.
Considerações Específicas do Aspire
Redis TLS (Aspire 13.1.0+)
Aspire 13.1.0 habilita TLS no Redis por padrão. Se você vir:
UntrustedRoot
nos erros de conexão Redis, o certificado de desenvolvimento não é confiável no nível do sistema. Execute o procedimento completo de recuperação acima.
Dashboard HTTPS do Aspire
O dashboard do Aspire usa o certificado de desenvolvimento para HTTPS. Se o dashboard mostrar avisos de certificado no navegador, o certificado não está no repositório de confiança do navegador. Para desenvolvimento, clicar para ignorar o aviso é aceitável — a confiança no nível do sistema (necessária para Redis, gRPC, etc.) é a prioridade.
ASPIRE_ALLOW_UNSECURED_TRANSPORT
Definir ASPIRE_ALLOW_UNSECURED_TRANSPORT=true é uma solução alternativa, não uma correção. Ele desabilita o TLS para comunicação entre serviços, o que:
- Mascara o problema de confiança subjacente
- Não corresponde ao comportamento de produção
- Pode causar bugs diferentes daqueles que você veria em produção
Corrija a confiança do certificado.
Ciclo de Vida do Certificado
O certificado de desenvolvimento é válido por 1 ano a partir da criação. Quando expirar:
dotnet dev-certs https --checkinformará que não há certificado válido- Execute o procedimento completo de recuperação para gerar um novo certificado
- O arquivo de certificado antigo em
/usr/local/share/ca-certificates/será substituído update-ca-certificatestrocará o certificado antigo pelo novo no pacote
Nenhuma reinicialização do sistema é necessária. As aplicações captam o novo pacote no próximo handshake TLS (reinicie sua aplicação).
Automação: Pipelines CI/CD
Em CI/CD em executores Linux, certificados de desenvolvimento raramente são necessários (você normalmente testa com certificados reais ou desabilita a validação TLS em estruturas de teste). No entanto, se seus testes de integração exigirem certificados de desenvolvimento confiáveis:
GitHub Actions
- name: Confiar no Certificado de Desenvolvimento .NET
run: |
dotnet dev-certs https
dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.crt --format PEM --no-password
sudo cp /tmp/dotnet-dev-cert.crt /usr/local/share/ca-certificates/dotnet-dev-cert.crt
sudo chmod 644 /usr/local/share/ca-certificates/dotnet-dev-cert.crt
rm /tmp/dotnet-dev-cert.crt
sudo update-ca-certificates
Azure DevOps
- script: |
dotnet dev-certs https
dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.crt --format PEM --no-password
sudo cp /tmp/dotnet-dev-cert.crt /usr/local/share/ca-certificates/dotnet-dev-cert.crt
sudo chmod 644 /usr/local/share/ca-certificates/dotnet-dev-cert.crt
rm /tmp/dotnet-dev-cert.crt
sudo update-ca-certificates
displayName: 'Confiar no Certificado de Desenvolvimento .NET'
Armadilhas Comuns
1. Certificado colocado, mas pacote nunca reconstruído
Sintoma: O arquivo de certificado existe em /usr/local/share/ca-certificates/ mas openssl verify falha.
Causa: update-ca-certificates nunca foi executado após colocar o arquivo.
Correção: sudo update-ca-certificates
Este é o erro mais comum. O diretório de CA é uma entrada para o processo de geração do pacote, não o pacote em si.
2. Arquivos de certificado obsoletos com permissões erradas
Sintoma: update-ca-certificates é executado, mas informa 0 added.
Causa: Arquivos de certificado com permissões 0600 são ilegíveis para update-ca-certificates (que é executado como root, mas lê arquivos por meio de um processo que pode verificar a legibilidade mundial). Os arquivos devem ser 644.
Correção: sudo chmod 644 /usr/local/share/ca-certificates/*.crt
3. Múltiplos arquivos de certificado de sessões diferentes
Sintoma: update-ca-certificates adiciona vários certificados, mas as aplicações ainda falham.
Causa: Arquivos de certificado antigos de ciclos anteriores de dotnet dev-certs https --clean / regeneração permanecem no diretório de CA. A impressão digital do certificado antigo não corresponde ao certificado de desenvolvimento atual.
Correção: Remova todos os arquivos dotnet* e aspnet*, depois re-exporte o certificado atual.
4. Incompatibilidade de impressão digital após limpeza/regeneração
Sintoma: openssl verify passa, mas o .NET ainda informa UntrustedRoot.
Causa: O certificado em /usr/local/share/ca-certificates/ foi exportado de um certificado de desenvolvimento anterior. Após dotnet dev-certs https --clean && dotnet dev-certs https, um novo certificado é gerado com uma impressão digital diferente. O arquivo no diretório de CA ainda contém o certificado antigo.
Correção: Execute o procedimento completo de recuperação para garantir que o certificado atual seja exportado e instalado.