Gerenciando certificados no Windows via PowerShell
1. Introdução aos Certificados Digitais no Windows
Certificados digitais são credenciais eletrônicas que vinculam uma identidade a um par de chaves criptográficas (pública e privada). No ecossistema Windows, eles são fundamentais para autenticação, assinatura de código, criptografia de e-mails e comunicações seguras via TLS/SSL. Uma Autoridade Certificadora (CA) é a entidade que emite e valida esses certificados.
O Windows armazena certificados em dois repositórios principais:
- Certificados do Computador Local (Cert:\LocalMachine): Acessíveis a todos os usuários e serviços do sistema.
- Certificados do Usuário Atual (Cert:\CurrentUser): Restritos ao perfil do usuário logado.
Para gerenciar esses certificados via PowerShell, utilizamos os cmdlets dos módulos PKI e Certificate. O módulo PKI oferece funcionalidades avançadas como importação/exportação, enquanto Certificate provê acesso ao provedor Cert:.
2. Navegando e Listando Certificados com PowerShell
O provedor Cert: permite navegar pelos repositórios como se fossem unidades de disco. Para listar todos os certificados no repositório pessoal do computador local:
Get-ChildItem -Path Cert:\LocalMachine\My
Para filtrar por propriedades específicas:
# Certificados com validade superior a 30 dias
Get-ChildItem -Path Cert:\CurrentUser\My | Where-Object { $_.NotAfter -gt (Get-Date).AddDays(30) }
# Certificados expirados
Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object { $_.NotAfter -lt (Get-Date) }
# Certificados por assunto (Subject)
Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object { $_.Subject -like "*contoso*" }
Localizando certificados prestes a expirar nos próximos 60 dias:
$expiringCerts = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {
$_.NotAfter -gt (Get-Date) -and $_.NotAfter -lt (Get-Date).AddDays(60)
}
$expiringCerts | Select-Object Subject, NotAfter, Thumbprint
3. Importação e Exportação de Certificados
Importando certificados
Para importar um arquivo PFX (inclui chave privada) com proteção por senha:
$password = ConvertTo-SecureString -String "MinhaSenha123" -AsPlainText -Force
Import-PfxCertificate -FilePath "C:\Certificados\meucert.pfx" `
-CertStoreLocation Cert:\LocalMachine\My -Password $password
Para importar um certificado sem chave privada (formato CER ou CRT):
Import-Certificate -FilePath "C:\Certificados\certificado.cer" `
-CertStoreLocation Cert:\CurrentUser\Root
Exportando certificados
Exportando com chave privada para PFX:
$cert = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object { $_.Subject -eq "CN=MeuSite" }
$password = ConvertTo-SecureString -String "OutraSenha456" -AsPlainText -Force
Export-PfxCertificate -Cert $cert -FilePath "C:\Backup\meusite.pfx" -Password $password
Exportando apenas o certificado público (CER):
Export-Certificate -Cert $cert -FilePath "C:\Backup\meusite.cer" -Type CERT
4. Criação de Certificados Autoassinados
O cmdlet New-SelfSignedCertificate permite gerar certificados para testes e ambientes de desenvolvimento:
# Certificado SSL para servidor web
New-SelfSignedCertificate -DnsName "www.meusite.local", "meusite.local" `
-CertStoreLocation Cert:\LocalMachine\My `
-FriendlyName "Certificado SSL Teste" `
-NotAfter (Get-Date).AddYears(2) `
-KeyUsage DigitalSignature, KeyEncipherment `
-TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.1") # Server Authentication
Criando certificado para assinatura de código:
New-SelfSignedCertificate -Type CodeSigning -Subject "CN=Meu Código" `
-CertStoreLocation Cert:\CurrentUser\My `
-NotAfter (Get-Date).AddYears(3)
5. Gerenciamento de Autoridades Certificadoras (CA)
Instalação de CA corporativa
Install-WindowsFeature -Name ADCS-Cert-Authority -IncludeManagementTools
Install-AdcsCertificationAuthority -CAType EnterpriseRootCa `
-CACommonName "Contoso Root CA" -KeyLength 4096 -ValidityPeriod Years -ValidityPeriodUnits 10
Emissão de certificados via CA
Usando CertReq.exe para solicitar certificado de uma CA corporativa:
# Criar arquivo de solicitação (.inf)
$infContent = @"
[NewRequest]
Subject = "CN=servidor.contoso.com"
KeySpec = 1
KeyLength = 2048
Exportable = TRUE
MachineKeySet = TRUE
SMIME = FALSE
PrivateKeyArchive = FALSE
UserProtected = FALSE
UseExistingKeySet = FALSE
ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
ProviderType = 12
RequestType = PKCS10
KeyUsage = 0xa0
[EnhancedKeyUsageExtension]
OID=1.3.6.1.5.5.7.3.1
"@
$infContent | Out-File -FilePath "C:\Temp\request.inf" -Encoding ASCII
# Gerar solicitação
certreq -new "C:\Temp\request.inf" "C:\Temp\request.req"
# Submeter à CA (substitua NomeDaCA)
certreq -submit -config "NomeDaCA\Contoso Root CA" "C:\Temp\request.req" "C:\Temp\cert.cer"
# Instalar o certificado emitido
certreq -accept "C:\Temp\cert.cer"
Revogação de certificados
# Revogar por thumbprint
certutil -revoke <Thumbprint> 1 # 1 = CA compromise
# Verificar CRL
certutil -crl
6. Automação de Tarefas de Manutenção
Backup automático de certificados pessoais
$backupDir = "C:\BackupCertificados\$(Get-Date -Format 'yyyy-MM-dd')"
New-Item -ItemType Directory -Path $backupDir -Force
$certs = Get-ChildItem -Path Cert:\LocalMachine\My
foreach ($cert in $certs) {
$filename = "$backupDir\$($cert.Subject -replace '[^\w\s]', '_').pfx"
$password = ConvertTo-SecureString -String "Backup2024!" -AsPlainText -Force
Export-PfxCertificate -Cert $cert -FilePath $filename -Password $password
}
Write-Output "Backup concluído em $backupDir"
Relatório de expiração com envio por e-mail
$expiring = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {
$_.NotAfter -lt (Get-Date).AddDays(90) -and $_.NotAfter -gt (Get-Date)
}
$htmlReport = $expiring | Select-Object Subject, NotAfter, Thumbprint |
ConvertTo-Html -Title "Relatório de Expiração de Certificados"
$htmlReport | Out-File "C:\Temp\expiration_report.html"
Send-MailMessage -To "admin@contoso.com" -From "noreply@contoso.com" `
-Subject "Relatório de Certificados Próximos ao Vencimento" `
-Body "Segue relatório em anexo." -Attachments "C:\Temp\expiration_report.html" `
-SmtpServer "smtp.contoso.com"
Remoção de certificados expirados
$expired = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object { $_.NotAfter -lt (Get-Date) }
foreach ($cert in $expired) {
Remove-Item -Path $cert.PSPath -DeleteKey
Write-Output "Removido: $($cert.Subject)"
}
7. Integração com Serviços e Aplicações
Associando certificados a sites IIS
$cert = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object { $_.Subject -eq "CN=www.meusite.local" }
New-WebBinding -Name "MeuSite" -Protocol https -Port 443 -IPAddress "*"
$binding = Get-IISSiteBinding -Name "MeuSite" -Protocol https
$binding.AddSslCertificate($cert.GetCertHash(), "my")
Configuração de certificado para RDP
$cert = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object { $_.Subject -eq "CN=servidor.contoso.com" }
$thumbprint = $cert.Thumbprint
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" `
-Name "SSLCertificateSHA1Hash" -Value $thumbprint
Restart-Service -Name "TermService"
Uso em autenticação de scripts
$cert = Get-ChildItem -Path Cert:\CurrentUser\My | Where-Object { $_.Subject -eq "CN=script@contoso.com" }
$response = Invoke-RestMethod -Uri "https://api.contoso.com/data" -Certificate $cert
8. Segurança e Boas Práticas
Proteção de chaves privadas
$certPath = "Cert:\LocalMachine\My\$($cert.Thumbprint)"
$acl = Get-Acl -Path $certPath
$permission = "BUILTIN\Administrators", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
$acl.SetAccessRule($accessRule)
Set-Acl -Path $certPath -AclObject $acl
Auditoria de operações com certificados
Get-WinEvent -LogName "Microsoft-Windows-CertificateServices-Client-Lifecycle-System/Operational" |
Where-Object { $_.TimeCreated -gt (Get-Date).AddDays(-7) } |
Select-Object TimeCreated, Id, Message
Estratégias de renovação automatizada
# Verificar certificados com menos de 30 dias de validade
$critical = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {
$_.NotAfter -lt (Get-Date).AddDays(30) -and $_.NotAfter -gt (Get-Date)
}
if ($critical.Count -gt 0) {
# Disparar renovação automática via CA
foreach ($cert in $critical) {
certreq -enroll -cert $cert.Thumbprint -config "NomeDaCA\Contoso Root CA"
}
}
Referências
- Documentação Oficial do Módulo PKI no PowerShell — Referência completa dos cmdlets para gerenciamento de certificados.
- Gerenciando Certificados com PowerShell no Windows Server — Guia oficial sobre o uso de certreq.exe para solicitação e gerenciamento de certificados.
- New-SelfSignedCertificate Cmdlet — Documentação detalhada sobre criação de certificados autoassinados.
- Provedor de Certificados do PowerShell — Explicação completa sobre navegação e manipulação do repositório Cert:.
- Boas Práticas para Gerenciamento de Certificados — Playbook de segurança da Microsoft para resposta a incidentes com certificados.
- Automatizando Renovação de Certificados com PowerShell — Tutorial prático de automação de renovação em ambientes corporativos.
- Gerenciamento de CA com PowerShell no Windows Server — Documentação oficial sobre cmdlets para administração de Autoridades Certificadoras.