Principais funções.

Função Get-NewCert

Esta é a função que recebe um parâmetro requser e gera um certificado para o usuário especificado. Ele usa a biblioteca .NET X509Enrollment para criar uma solicitação de certificado, solicitar um certificado usando a solicitação e gravar o certificado em um arquivo PFX.

function Get-NewCert {
    param (
        [Parameter()]
        [string] $requser
    )

    $PKCS10 = New-Object -ComObject X509Enrollment.CX509CertificateRequestPkcs10
    $PKCS10.InitializeFromTemplateName(0x1,$TemplateName)
    $PKCS10.Encode()
    $pkcs7 = New-Object -ComObject X509enrollment.CX509CertificateRequestPkcs7
    $pkcs7.InitializeFromInnerRequest($pkcs10)
    $pkcs7.RequesterName = $DomainSuffixSplit+"\"+$requser
    $signer = New-Object -ComObject X509Enrollment.CSignerCertificate
    $signer.Initialize(0,0,0xc,$UserCertThumbPrint)
    $pkcs7.SignerCertificate = $signer
    $Request = New-Object -ComObject X509Enrollment.CX509Enrollment
    $Request.InitializeFromRequest($pkcs7)
    $Request.Enroll()
    try {
        $Request.Enroll()
    } catch {
        Write-Host "Erro ao gerar o certificado. Verifique se o usuário $UserCertSubject possui permissão para gerar certificados com o template "$TemplateName" e se o certificado está instalado na máquina."
        exit
    }
}

Definindo as variáveis

As variáveis de configuração do script são definidas no início do script. O nome do domínio, o nome do modelo de certificado, o Thumbprint do certificado do usuário e o caminho onde os certificados serão salvos são definidos aqui.

Define o nome do seu domínio, split do sufixo, template e ThumbPrit do Certificado a ser usado.

$DomainName = "contoso.com"
$DomainSuffixSplit = $DomainName.Split(".")[0]
$TemplateName = "contosoUser"
$UserCertThumbPrint = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Define o caminho para salvar os certificados e senha

$CertPath = "C:\temp\certs\"

Solicitando o nome do usuário

O script solicita o nome do usuário para o qual um certificado será gerado. Se o usuário não for encontrado, o script solicita ao usuário se ele deseja tentar novamente ou sair.

do {
    $UserName = Read-Host "Digite o nome do usuário para gerar o Certificado"

    # Realiza a pesquisa do usuário no Active Directory
    $User = Get-ADUser -Filter { SamAccountName -eq $UserName } -Properties SamAccountName,DistinguishedName -Server $DomainName

    if ($User -eq $null) {
        Write-Host "Usuário $UserName não encontrado no AD. Deseja digitar outro usuário? (S/N)"
        $opcao = Read-Host
        if ($opcao -eq "N") {
            exit
        }
    }
} while ($User -eq $null)

Verificando se o usuário já tem um certificado válido

Se o usuário já tiver um certificado válido, o script pergunta ao usuário se ele deseja renovar o certificado ou exportar o certificado existente. O script também verifica se o certificado existente está prestes a expirar. Se o usuário escolher exportar o certificado existente, o script exportará o certificado para um arquivo PFX e salvará a senha em um arquivo de texto.

if ((Get-ChildItem -Path "Cert:\CurrentUser\My" -DnsName $requser -ErrorAction SilentlyContinue) -and (Get-ChildItem -Path "Cert:\CurrentUser\My" -DnsName $requser).NotAfter -gt (Get-Date).AddDays(30)) {
    $resp = Read-Host "Usuário já possui um certificado válido que não está prestes a expirar. `nDeseja renovar o certificado ou exportar o certificado já existente? `n(R - Renovar / E - Exportar)(Default = Exportar)"
    if ($resp -eq "R" -or $resp -eq "r") {
        Get-NewCert -requser $requser        
        Get-ChildItem -Path cert:\CurrentUser\my | Where-Object -Property Subject -eq $subject | Export-PfxCertificate -NoProperties -FilePath $attcert -Password (ConvertTo-SecureString -String $passwd -Force -AsPlainText)
        Write-Host "Certificado gerado com sucesso."
        Write-Host "O certificado foi salvo em $attcert."
        Write-Host "A senha foi salva em $PassFileName."
    
        # Grava a senha gerada no arquivo de texto
        $passwd | Out-File $PassFileName

    } elseif ($resp -eq "E" -or $resp -eq "e" -or $resp -eq "" ) {
        Get-ChildItem -Path cert:\CurrentUser\my | Where-Object -Property Subject -eq $subject | Export-PfxCertificate -NoProperties -FilePath $attcert -Password (ConvertTo-SecureString -String $passwd -Force -AsPlainText)
        $passwd | Out-File $PassFileName
        Write-Host "Certificado exportado com sucesso."
        Write-Host "A senha foi salva em $PassFileName."
    } else {
        Write-Host "Opção inválida."
    }
} else {
    Get-NewCert -requser $requser        
    Get-ChildItem -Path cert:\CurrentUser\my | Where-Object -Property Subject -eq $subject | Export-PfxCertificate -NoProperties -FilePath $attcert -Password (ConvertTo-SecureString -String $passwd -Force -AsPlainText)
    Write-Host "Certificado gerado com sucesso."
    Write-Host "O certificado foi salvo em $attcert."
    Write-Host "A senha foi salva em $PassFileName."

    # Grava a senha gerada no arquivo de texto
    $passwd | Out-File $PassFileName
}

Princiais comandos e variáveis

  • Get-NewCert: função que gera um novo certificado com base nos parâmetros informados.
  • $DomainName: nome do domínio do Active Directory.
  • $DomainSuffixSplit: prefixo do nome do domínio.
  • $TemplateName: nome do template de certificado.
  • $UserCertThumbPrint: impressão digital do certificado do usuário atual.
  • $UserCert: objeto que contém as informações do certificado do usuário.
  • $UserCertSubject: assunto do certificado do usuário atual.
  • $CertPath: caminho para salvar os certificados gerados.
  • $UserName: nome do usuário informado pelo usuário.
  • Get-ADUser: cmdlet do PowerShell que retorna um objeto de usuário do Active Directory com base no filtro fornecido.
  • $User: objeto de usuário do Active Directory correspondente ao nome de usuário fornecido.
  • $requser: nome de usuário SAMAccountName.
  • $subject: assunto do certificado.
  • $attcert: caminho para salvar o arquivo de certificado.
  • $PassFileName: caminho para salvar o arquivo de senha do certificado.
  • Get-ChildItem: cmdlet do PowerShell que retorna uma lista de itens em um determinado caminho.
  • Export-PfxCertificate: cmdlet do PowerShell que exporta um certificado para um arquivo PFX.
  • $resp: resposta do usuário à pergunta se deseja renovar ou exportar um certificado existente.
  • Write-Host: cmdlet do PowerShell que exibe mensagens na tela.
  • $passwd: senha gerada aleatoriamente para proteger o arquivo PFX do certificado.
  • Out-File: cmdlet do PowerShell que salva uma saída em um arquivo.
  • try, catch: bloco de tratamento de erros do PowerShell.
  • $PKCS10: objeto PKCS10 usado para solicitar um certificado.
  • $PKCS10.InitializeFromTemplateName(): método usado para inicializar o objeto PKCS10 com o nome do template de certificado.
  • $PKCS10.Encode(): método usado para codificar o objeto PKCS10.
  • $pkcs7: objeto PKCS7 usado para encapsular a solicitação de certificado.
  • $pkcs7.InitializeFromInnerRequest(): método usado para inicializar o objeto PKCS7 com a solicitação de certificado encapsulada.
  • $pkcs7.RequesterName: nome do solicitante do certificado.
  • $signer: objeto que representa o certificado do assinante.
  • $signer.Initialize(): método usado para inicializar o objeto CSignerCertificate com o certificado do assinante.
  • $Request: objeto CX509Enrollment usado para solicitar o certificado.
  • $Request.InitializeFromRequest(): método usado para inicializar o objeto CX509Enrollment com a solicitação de certificado.
  • $Request.Enroll(): método usado para enviar a solicitação de certificado para a autoridade de certificação.
  • param: palavra-chave usada para definir os parâmetros de entrada da função Get-NewCert.
  • [Parameter()]: atributo usado para definir as propriedades do parâmetro $requser.
  • Write-Error: cmdlet do PowerShell usado para exibir uma mensagem de erro e encerrar a execução do script.
  • Test-Path -Path $CertPath -PathType Container: cmdlet do PowerShell usado para verificar se o caminho especificado é um diretório válido.
  • New-Item -ItemType Directory -Path $CertPath: cmdlet do PowerShell usado para criar um diretório no caminho especificado.
  • Read-Host: cmdlet do PowerShell usado para solicitar entrada do usuário.
  • Filter: parâmetro usado para filtrar a pesquisa de usuários.
  • { SamAccountName -eq $UserName }: propriedade e valor usados para filtrar a pesquisa de usuários pelo nome de usuário.
  • -Properties SamAccountName,DistinguishedName: parâmetro usado para especificar quais propriedades de usuário recuperar.
  • -Server $DomainName: parâmetro usado para especificar qual controlador de domínio do Active Directory realizar a pesquisa de usuários.
  • $User: objeto que contém as informações do usuário pesquisado.
  • $User.SamAccountName: propriedade que contém o nome de usuário do usuário pesquisado.
  • $User.distinguishedName: propriedade que contém o nome distintivo do usuário pesquisado.
  • $subject: nome distintivo do usuário pesquisado formatado para salvar no arquivo PFX do certificado.
  • $UserName + ".pfx": nome do arquivo PFX do certificado a ser gerado.
  • if ((Get-ChildItem -Path "Cert:\CurrentUser\My" -DnsName $requser -ErrorAction SilentlyContinue) -and (Get-ChildItem -Path "Cert:\CurrentUser\My" -DnsName $requser).NotAfter -gt (Get-Date).AddDays(30)): condição usada para verificar se o usuário já possui um certificado válido que não está prestes a expirar.
  • Get-Date: cmdlet do PowerShell que retorna a data e hora atuais.
  • Renovar / Exportar: opções oferecidas ao usuário para renovar ou exportar o certificado existente.
  • Exit: cmdlet do PowerShell que finaliza a execução do script.

Obs: Este é o script para gerar certificados para usuários do Active Directory. Certifique-se de modificar as variáveis de configuração no início do script de acordo com sua configuração e use-o com cuidado.

Codigo completo

# Função que recebe parametro e gera certificado.
function Get-NewCert {
    param (
        [Parameter()]
        [string] $requser
    )

    $PKCS10 = New-Object -ComObject X509Enrollment.CX509CertificateRequestPkcs10
    # Object identifier do Certificate template
    $PKCS10.InitializeFromTemplateName(0x1,$TemplateName)
    $PKCS10.Encode()
    $pkcs7 = New-Object -ComObject X509enrollment.CX509CertificateRequestPkcs7
    $pkcs7.InitializeFromInnerRequest($pkcs10)
    $pkcs7.RequesterName = $DomainSuffixSplit+"\"+$requser
    $signer = New-Object -ComObject X509Enrollment.CSignerCertificate
    $signer.Initialize(0,0,0xc,$UserCertThumbPrint)
    $pkcs7.SignerCertificate = $signer
    $Request = New-Object -ComObject X509Enrollment.CX509Enrollment
    $Request.InitializeFromRequest($pkcs7)
    $Request.Enroll()
    try {
        $Request.Enroll()
    } catch {
        Write-Host "Erro ao gerar o certificado. Verifique se o usuário $UserCertSubject possui permissão para gerar certificados com o template "$TemplateName" e se o certificado está instalado na máquina."
        exit
    }
}

# Define o nome do seu domínio
$DomainName = "contoso.com"
$DomainSuffixSplit = $DomainName.Split(".")[0]
$TemplateName = "contosoUser"
$UserCertThumbPrint = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
$UserCert = Get-ChildItem -Path Cert:\CurrentUser\My | Where-Object {$_.Thumbprint -eq $UserCertThumbPrint}
if ($UserCert -eq $null) {
    Write-Error "O certificado com Thumbprint $UserCertThumbPrint não foi encontrado."
    Exit
}
$UserCertSubject = $UserCert.Subject.Split(",")[0]

# Define o caminho para salvar os certificados
$CertPath = "C:\temp\certs\"
if (-not (Test-Path -Path $CertPath -PathType Container)) {
    Write-Host "Diretório $CertPath não existe. Criando diretório."
    New-Item -ItemType Directory -Path $CertPath
}

# Solicita o nome do usuário
do {
    $UserName = Read-Host "Digite o nome do usuário para gerar o Certificado"

    # Realiza a pesquisa do usuário no Active Directory
    $User = Get-ADUser -Filter { SamAccountName -eq $UserName } -Properties SamAccountName,DistinguishedName -Server $DomainName

    if ($User -eq $null) {
        Write-Host "Usuário $UserName não encontrado no AD. Deseja digitar outro usuário? (S/N)"
        $opcao = Read-Host
        if ($opcao -eq "N") {
            exit
        }
    }
} while ($User -eq $null)

$requser = $User.SamAccountName.ToString()
$subject = $User.distinguishedName.Replace(",",", ")
$passwd = ("!@0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".tochararray() | Sort-Object {Get-Random})[0..6] -join ''
$attcert = $CertPath + $UserName + ".pfx"
$PassFileName = $CertPath + $UserName + "-pass.txt"


# Verifica se o usuário já possui um certificado emitido ou se o certificado existente está prestes a expirar
if ((Get-ChildItem -Path "Cert:\CurrentUser\My" -DnsName $requser -ErrorAction SilentlyContinue) -and (Get-ChildItem -Path "Cert:\CurrentUser\My" -DnsName $requser).NotAfter -gt (Get-Date).AddDays(30)) {
    $resp = Read-Host "Usuário já possui um certificado válido que não está prestes a expirar. `nDeseja renovar o certificado ou exportar o certificado já existente? `n(R - Renovar / E - Exportar)(Default = Exportar)"
    if ($resp -eq "R" -or $resp -eq "r") {
        Get-NewCert -requser $requser        
        Get-ChildItem -Path cert:\CurrentUser\my | Where-Object -Property Subject -eq $subject | Export-PfxCertificate -NoProperties -FilePath $attcert -Password (ConvertTo-SecureString -String $passwd -Force -AsPlainText)
        Write-Host "Certificado gerado com sucesso."
        Write-Host "O certificado foi salvo em $attcert."
        Write-Host "A senha foi salva em $PassFileName."
    
        # Grava a senha gerada no arquivo de texto
        $passwd | Out-File $PassFileName

    } elseif ($resp -eq "E" -or $resp -eq "e" -or $resp -eq "" ) {
        Get-ChildItem -Path cert:\CurrentUser\my | Where-Object -Property Subject -eq $subject | Export-PfxCertificate -NoProperties -FilePath $attcert -Password (ConvertTo-SecureString -String $passwd -Force -AsPlainText)
        $passwd | Out-File $PassFileName
        Write-Host "Certificado exportado com sucesso."
        Write-Host "A senha foi salva em $PassFileName."
    } else {
        Write-Host "Opção inválida."
    }
} else {
    Get-NewCert -requser $requser        
    Get-ChildItem -Path cert:\CurrentUser\my | Where-Object -Property Subject -eq $subject | Export-PfxCertificate -NoProperties -FilePath $attcert -Password (ConvertTo-SecureString -String $passwd -Force -AsPlainText)
    Write-Host "Certificado gerado com sucesso."
    Write-Host "O certificado foi salvo em $attcert."
    Write-Host "A senha foi salva em $PassFileName."

    # Grava a senha gerada no arquivo de texto
    $passwd | Out-File $PassFileName
}