426 lines
10 KiB
Markdown
426 lines
10 KiB
Markdown
# Troubleshooting Certificate Generation Issues
|
|
|
|
## Common Error: "Smart card select a smart card device the security device is read-only"
|
|
|
|
This error occurs when using `New-SelfSignedCertificate` on systems with:
|
|
- Smart card policies enforced by Group Policy
|
|
- Smart card readers attached
|
|
- Restricted certificate store permissions
|
|
- TPM (Trusted Platform Module) restrictions
|
|
|
|
### Quick Fixes
|
|
|
|
#### Fix 1: Use Alternative Certificate Generation Script
|
|
|
|
```powershell
|
|
# Use the alternative script that bypasses smart card issues
|
|
.\Generate-WildcardCert-Alternative.ps1
|
|
```
|
|
|
|
This script uses `certreq.exe` instead of `New-SelfSignedCertificate` to avoid smart card device errors.
|
|
|
|
---
|
|
|
|
#### Fix 2: Temporarily Disable Smart Card Service
|
|
|
|
```powershell
|
|
# Stop smart card service temporarily
|
|
Stop-Service -Name "SCardSvr" -Force
|
|
|
|
# Run certificate generation
|
|
.\Generate-WildcardCert.ps1
|
|
|
|
# Restart service
|
|
Start-Service -Name "SCardSvr"
|
|
```
|
|
|
|
**Note:** Requires Administrator privileges. May affect other applications using smart cards.
|
|
|
|
---
|
|
|
|
#### Fix 3: Use Different Crypto Provider
|
|
|
|
```powershell
|
|
# Generate certificate with specific provider
|
|
$cert = New-SelfSignedCertificate `
|
|
-DnsName "*.logon.ds.ge.com", "logon.ds.ge.com" `
|
|
-CertStoreLocation "Cert:\LocalMachine\My" `
|
|
-Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" `
|
|
-KeyExportPolicy Exportable `
|
|
-KeySpec KeyExchange `
|
|
-NotAfter (Get-Date).AddYears(2)
|
|
```
|
|
|
|
---
|
|
|
|
#### Fix 4: Generate Certificate via CertReq
|
|
|
|
**Step 1: Create request file**
|
|
|
|
Create `cert-request.inf`:
|
|
```ini
|
|
[Version]
|
|
Signature="$Windows NT$"
|
|
|
|
[NewRequest]
|
|
Subject="CN=*.logon.ds.ge.com"
|
|
KeyLength=2048
|
|
KeyAlgorithm=RSA
|
|
HashAlgorithm=SHA256
|
|
MachineKeySet=TRUE
|
|
Exportable=TRUE
|
|
RequestType=Cert
|
|
KeyUsage=0xA0
|
|
KeyUsageProperty=0x02
|
|
|
|
[Extensions]
|
|
2.5.29.17 = "{text}"
|
|
_continue_ = "dns=*.logon.ds.ge.com&"
|
|
_continue_ = "dns=logon.ds.ge.com&"
|
|
|
|
2.5.29.37 = "{text}"
|
|
_continue_ = "1.3.6.1.5.5.7.3.1,"
|
|
|
|
[EnhancedKeyUsageExtension]
|
|
OID=1.3.6.1.5.5.7.3.1
|
|
```
|
|
|
|
**Step 2: Generate certificate**
|
|
|
|
```powershell
|
|
# Create certificate using certreq
|
|
certreq.exe -new -f cert-request.inf wildcard.cer
|
|
|
|
# Find the certificate
|
|
$cert = Get-ChildItem Cert:\LocalMachine\My |
|
|
Where-Object { $_.Subject -like "*logon.ds.ge.com*" } |
|
|
Sort-Object NotBefore -Descending |
|
|
Select-Object -First 1
|
|
|
|
# Export to PFX
|
|
$password = ConvertTo-SecureString "YourPassword" -AsPlainText -Force
|
|
Export-PfxCertificate -Cert $cert `
|
|
-FilePath "wildcard-logon-ds-ge-com.pfx" `
|
|
-Password $password
|
|
```
|
|
|
|
---
|
|
|
|
#### Fix 5: Generate on Different Computer
|
|
|
|
If the above methods don't work, generate the certificate on a computer without smart card restrictions:
|
|
|
|
1. **Generate on unrestricted computer:**
|
|
```powershell
|
|
.\Generate-WildcardCert.ps1
|
|
```
|
|
|
|
2. **Copy PFX file to restricted computer:**
|
|
```powershell
|
|
Copy-Item "wildcard-*.pfx" -Destination "\\RestrictedComputer\C$\Temp\"
|
|
```
|
|
|
|
3. **Use on restricted computer:**
|
|
```powershell
|
|
.\Setup-WinRM-HTTPS.ps1 -CertificatePath "C:\Temp\wildcard-*.pfx" `
|
|
-Domain "logon.ds.ge.com"
|
|
```
|
|
|
|
---
|
|
|
|
## Other Common Certificate Errors
|
|
|
|
### Error: "Access Denied" When Creating Certificate
|
|
|
|
**Cause:** Insufficient permissions on certificate store
|
|
|
|
**Solution:**
|
|
```powershell
|
|
# Run PowerShell as Administrator
|
|
# Right-click PowerShell Run as Administrator
|
|
|
|
# Verify admin rights
|
|
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
|
if (-not $isAdmin) {
|
|
Write-Error "This script requires Administrator privileges"
|
|
exit 1
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Error: "The parameter is incorrect" When Exporting
|
|
|
|
**Cause:** Password not in correct format
|
|
|
|
**Solution:**
|
|
```powershell
|
|
# Ensure password is SecureString
|
|
$password = Read-Host "Enter password" -AsSecureString
|
|
|
|
# NOT this (unless using -AsPlainText -Force)
|
|
# $password = "MyPassword" # Wrong type
|
|
```
|
|
|
|
---
|
|
|
|
### Error: "Cannot export non-exportable private key"
|
|
|
|
**Cause:** Certificate created without exportable flag
|
|
|
|
**Solution:**
|
|
```powershell
|
|
# When creating, ensure KeyExportPolicy is Exportable
|
|
$cert = New-SelfSignedCertificate `
|
|
-DnsName "*.logon.ds.ge.com" `
|
|
-KeyExportPolicy Exportable ` # Important!
|
|
-CertStoreLocation "Cert:\LocalMachine\My"
|
|
```
|
|
|
|
If already created, you must recreate the certificate.
|
|
|
|
---
|
|
|
|
### Error: "The trust chain could not be established"
|
|
|
|
**Cause:** Self-signed certificate not in Trusted Root store
|
|
|
|
**Solution:**
|
|
```powershell
|
|
# Import to Trusted Root
|
|
$cert = Get-ChildItem Cert:\LocalMachine\My |
|
|
Where-Object { $_.Subject -like "*logon.ds.ge.com*" }
|
|
|
|
$rootStore = New-Object System.Security.Cryptography.X509Certificates.X509Store(
|
|
"Root", "LocalMachine"
|
|
)
|
|
$rootStore.Open("ReadWrite")
|
|
$rootStore.Add($cert)
|
|
$rootStore.Close()
|
|
|
|
Write-Host "Certificate added to Trusted Root"
|
|
```
|
|
|
|
---
|
|
|
|
## Group Policy Restrictions
|
|
|
|
### Check if Group Policy Restricts Certificates
|
|
|
|
```powershell
|
|
# Check certificate template policies
|
|
gpresult /H gpreport.html
|
|
# Open gpreport.html and search for "Certificate"
|
|
|
|
# Check smart card policies
|
|
Get-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\Windows\SmartCardCredentialProvider"
|
|
```
|
|
|
|
### Workarounds for Group Policy
|
|
|
|
1. **Request exception from IT security team**
|
|
- Explain need for WinRM HTTPS testing
|
|
- Request temporary policy exemption
|
|
|
|
2. **Use test environment without policies**
|
|
- VM or workstation not in domain
|
|
- Generate certificates there
|
|
|
|
3. **Get certificate from Certificate Authority**
|
|
- Request wildcard cert from internal CA
|
|
- Avoids self-signed certificate issues
|
|
|
|
---
|
|
|
|
## Alternative: Use Existing Certificate
|
|
|
|
If you cannot generate certificates, use an existing one:
|
|
|
|
### Option 1: Use Existing Machine Certificate
|
|
|
|
```powershell
|
|
# Find existing exportable certificates
|
|
Get-ChildItem Cert:\LocalMachine\My |
|
|
Where-Object {
|
|
$_.HasPrivateKey -and
|
|
$_.Extensions | Where-Object { $_.Oid.FriendlyName -eq "Key Usage" }
|
|
} |
|
|
Select-Object Subject, Thumbprint, NotAfter
|
|
|
|
# Use existing certificate by thumbprint
|
|
.\Setup-WinRM-HTTPS.ps1 -CertificateThumbprint "ABC123..." `
|
|
-Domain "logon.ds.ge.com"
|
|
```
|
|
|
|
### Option 2: Import Existing PFX
|
|
|
|
```powershell
|
|
# If you have a PFX file from elsewhere
|
|
$password = Read-Host "Enter PFX password" -AsSecureString
|
|
Import-PfxCertificate -FilePath "existing-cert.pfx" `
|
|
-CertStoreLocation "Cert:\LocalMachine\My" `
|
|
-Password $password `
|
|
-Exportable
|
|
|
|
# Use it
|
|
$cert = Get-ChildItem Cert:\LocalMachine\My |
|
|
Where-Object { $_.Subject -like "*your-domain*" }
|
|
|
|
.\Setup-WinRM-HTTPS.ps1 -CertificateThumbprint $cert.Thumbprint `
|
|
-Domain "logon.ds.ge.com"
|
|
```
|
|
|
|
---
|
|
|
|
## Using OpenSSL (Advanced)
|
|
|
|
If PowerShell methods fail completely, use OpenSSL:
|
|
|
|
### Install OpenSSL
|
|
|
|
```powershell
|
|
# Install via Chocolatey
|
|
choco install openssl -y
|
|
|
|
# Or download from: https://slproweb.com/products/Win32OpenSSL.html
|
|
```
|
|
|
|
### Generate Certificate with OpenSSL
|
|
|
|
```bash
|
|
# Generate private key
|
|
openssl genrsa -out wildcard.key 2048
|
|
|
|
# Generate certificate signing request
|
|
openssl req -new -key wildcard.key -out wildcard.csr -subj "/CN=*.logon.ds.ge.com"
|
|
|
|
# Create config file for SAN
|
|
cat > openssl.cnf << EOF
|
|
[req]
|
|
distinguished_name = req_distinguished_name
|
|
req_extensions = v3_req
|
|
|
|
[req_distinguished_name]
|
|
|
|
[v3_req]
|
|
subjectAltName = @alt_names
|
|
|
|
[alt_names]
|
|
DNS.1 = *.logon.ds.ge.com
|
|
DNS.2 = logon.ds.ge.com
|
|
EOF
|
|
|
|
# Generate self-signed certificate
|
|
openssl x509 -req -days 730 -in wildcard.csr -signkey wildcard.key \
|
|
-out wildcard.crt -extensions v3_req -extfile openssl.cnf
|
|
|
|
# Create PFX
|
|
openssl pkcs12 -export -out wildcard.pfx \
|
|
-inkey wildcard.key -in wildcard.crt \
|
|
-passout pass:YourPassword
|
|
```
|
|
|
|
### Import OpenSSL Certificate
|
|
|
|
```powershell
|
|
# Import the PFX created by OpenSSL
|
|
$password = ConvertTo-SecureString "YourPassword" -AsPlainText -Force
|
|
Import-PfxCertificate -FilePath "wildcard.pfx" `
|
|
-CertStoreLocation "Cert:\LocalMachine\My" `
|
|
-Password $password `
|
|
-Exportable
|
|
```
|
|
|
|
---
|
|
|
|
## Verification Steps
|
|
|
|
After generating certificate by any method:
|
|
|
|
```powershell
|
|
# 1. Verify certificate exists
|
|
$cert = Get-ChildItem Cert:\LocalMachine\My |
|
|
Where-Object { $_.Subject -like "*logon.ds.ge.com*" }
|
|
|
|
if ($cert) {
|
|
Write-Host "Certificate found!" -ForegroundColor Green
|
|
Write-Host "Subject: $($cert.Subject)"
|
|
Write-Host "Thumbprint: $($cert.Thumbprint)"
|
|
Write-Host "Has Private Key: $($cert.HasPrivateKey)"
|
|
Write-Host "Expires: $($cert.NotAfter)"
|
|
} else {
|
|
Write-Host "Certificate not found!" -ForegroundColor Red
|
|
}
|
|
|
|
# 2. Verify exportable
|
|
if ($cert.PrivateKey.CspKeyContainerInfo.Exportable) {
|
|
Write-Host "Private key is exportable" -ForegroundColor Green
|
|
} else {
|
|
Write-Host "Private key is NOT exportable" -ForegroundColor Red
|
|
}
|
|
|
|
# 3. Test export
|
|
try {
|
|
$testPassword = ConvertTo-SecureString "test" -AsPlainText -Force
|
|
$testPath = "$env:TEMP\test-export.pfx"
|
|
Export-PfxCertificate -Cert $cert -FilePath $testPath -Password $testPassword
|
|
Remove-Item $testPath -Force
|
|
Write-Host "Export test successful" -ForegroundColor Green
|
|
} catch {
|
|
Write-Host "Export test failed: $($_.Exception.Message)" -ForegroundColor Red
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Getting Help
|
|
|
|
If none of these solutions work:
|
|
|
|
1. **Check Event Viewer:**
|
|
```powershell
|
|
# View certificate-related errors
|
|
Get-EventLog -LogName Application -Source "Microsoft-Windows-CertificateServicesClient-CertEnroll" -Newest 10
|
|
```
|
|
|
|
2. **Enable certificate logging:**
|
|
```powershell
|
|
# Enable detailed certificate logging
|
|
wevtutil sl Microsoft-Windows-CertificateServicesClient-Lifecycle-System /e:true
|
|
wevtutil sl Microsoft-Windows-CertificateServicesClient-Lifecycle-User /e:true
|
|
```
|
|
|
|
3. **Check Group Policy settings:**
|
|
```powershell
|
|
gpresult /H C:\Temp\gpreport.html
|
|
# Open and search for certificate or smart card policies
|
|
```
|
|
|
|
4. **Test with makecert (legacy):**
|
|
```powershell
|
|
# If available (older Windows SDK)
|
|
makecert -r -pe -n "CN=*.logon.ds.ge.com" -sky exchange -ss my
|
|
```
|
|
|
|
5. **Contact IT/Security team:**
|
|
- Request certificate from internal CA
|
|
- Request policy exemption
|
|
- Request assistance with certificate generation
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
**Recommended approach when you see smart card error:**
|
|
|
|
1. Try `Generate-WildcardCert-Alternative.ps1` (uses certreq)
|
|
2. Try disabling smart card service temporarily
|
|
3. Try different crypto provider
|
|
4. Generate on different computer without restrictions
|
|
5. Request certificate from your organization's CA
|
|
|
|
**For production deployment:**
|
|
- Always get certificates from trusted Certificate Authority
|
|
- Self-signed certificates are for testing only
|
|
- Document any workarounds used
|