MSCA API
部署和保护 CA-API Proxy Gateway,将 Microsoft Enterprise 或 Standalone CA 集成到 PKI Trust Manager。
📋 概述#
CA-API Proxy Gateway 是一个 .NET 应用程序,作为 PKI Trust Manager 与 Microsoft Certificate Authority (CA) 之间的安全代理。它提供 RESTful API,用于管理 Microsoft Enterprise CA 或 Standalone CA 证书。
🏗️ 架构#
┌─────────────────────────────────────────────────────────┐
│ PKI Trust Manager │
├─────────────────────────────────────────────────────────┤
│ CA-API Proxy Gateway │
│ (This Application - REST API) │
├─────────────────────────────────────────────────────────┤
│ Microsoft Certificate Authority │
│ (Enterprise CA or Standalone CA) │
└─────────────────────────────────────────────────────────┘
📋 前提条件#
I. 软件要求#
Windows Server 功能
# Install required Windows features
Install-WindowsFeature -Name Web-Server,Web-Asp-Net45,Web-ISAPI-Ext,Web-ISAPI-Filter.NET Framework 4.7.2 或更高版本
- 下载地址:https://dotnet.microsoft.com/download/dotnet-framework
- 必需组件:
- HTTP Activation
- .NET Extensibility
- ISAPI Extensions
- ISAPI Filters
II. 环境要求#
Microsoft Enterprise CA
- 部署到任何加入 Active Directory 的 Windows Server。
- 服务器必须能够通过网络访问 CA 服务器。
Microsoft Standalone CA
- 直接部署到 CA 服务器上。
- 无需加入 Active Directory。
📁 目录结构#
默认应用程序目录
C:\Sites\ca-api-proxy\
├── bin\ # Application binaries
├── ca\ # CA Certificate files (required!)
│ ├── cacert.crt # CA Certificate (PEM format) - REQUIRED
│ └── cachain.crt # Full CA Chain (PEM format) - REQUIRED
├── logs\ # Application logs
├── web.config # Configuration file
└── (other web files)
可选外部日志目录
C:\Logs\ca-api-proxy\
└── (daily log files)
🔐 安全配置#
服务帐户设置
创建专用服务帐户(例如 svc-caapi):
1. 添加到 IIS_IUSRS 组
# Add service account to IIS_IUSRS
net localgroup IIS_IUSRS svc-caapi /add2. 授予 CA 管理权限
- 打开 Certification Authority 控制台。
- 右键单击 CA 名称 → Properties → Security 选项卡。
- 为服务帐户添加以下权限:
- Read Configuration
- Issue, Manage Certificates
- Manage CA
- Request Certificates
3. 设置目录权限
通过图形界面或 PowerShell 为服务帐户授予应用目录的完全控制权限:
# Grant full control to application directory
icacls "C:\Sites\ca-api-proxy" /grant "svc-caapi:(OI)(CI)F"
# Grant full control to ca folder specifically
icacls "C:\Sites\ca-api-proxy\ca" /grant "svc-caapi:(OI)(CI)F"
# Grant full control to log directory (if external)
icacls "C:\Logs\ca-api-proxy" /grant "svc-caapi:(OI)(CI)F"4. 服务帐户属性
- 密码永不过期。
- 用户不能更改密码。
- 作为服务登录(可选)。
🚀 部署步骤#
步骤 1:安装 IIS 和 .NET 功能#
# Run PowerShell as Administrator
# Install IIS with required features
Install-WindowsFeature -Name `
Web-Server, `
Web-ASP-Net45, `
Web-ISAPI-Ext, `
Web-ISAPI-Filter, `
Web-Asp-Net, `
Web-Net-Ext, `
Web-ISAPI-Ext, `
Web-ISAPI-Filter, `
Web-Http-Redirect, `
Web-Filtering, `
Web-Basic-Auth, `
Web-Windows-Auth, `
Web-Digest-Auth
# Install.NET Framework 4.7.2 (if not already installed)
# Download from: https://dotnet.microsoft.com/download/dotnet-framework/net472步骤 2:创建应用程序目录#
# Create application directory structure
New-Item -ItemType Directory -Path "C:\Sites\ca-api-proxy" -Force
New-Item -ItemType Directory -Path "C:\Sites\ca-api-proxy\ca" -Force # IMPORTANT: This folder is required
New-Item -ItemType Directory -Path "C:\Sites\ca-api-proxy\logs" -Force步骤 3:部署应用程序文件#
将以下文件复制到 C:\Sites\ca-api-proxy\:
- 所有 .NET 二进制文件及其依赖项。
web.config文件。
步骤 4:配置 IIS 网站#
使用 IIS Manager
- 打开 Internet Information Services (IIS) Manager。
- 右键单击 Sites → Add Website。
- 配置:
- Site name:
ca-api-proxy - Physical path:
C:\Sites\ca-api-proxy - Binding:
- Type:
http - IP address:
All Unassigned(或指定 IP) - Port:
9081(建议) - Host name:留空
- Type:
- Site name:
- 单击 OK。
使用 PowerShell
# Import IIS module
Import-Module WebAdministration
# Create new website
New-Website -Name "ca-api-proxy" `
-PhysicalPath "C:\Sites\ca-api-proxy" `
-Port 9081 `
-Force步骤 5:配置应用程序池#
使用 IIS Manager
- 转到 Application Pools。
- 找到
ca-api-proxy池(自动创建)。 - 右键单击 → Advanced Settings。
- 设置:
- .NET CLR version:
.NET CLR Version v4.0.30319 - Managed pipeline mode:
Integrated - Identity:
svc-caapi(您的服务帐户) - Load User Profile:
True
- .NET CLR version:
使用 PowerShell
安全警告:
YourPassword123!仅为示例值。请替换为独有且安全的密码;生产环境中切勿使用示例密码。
# Set application pool identity
Set-ItemProperty "IIS:\AppPools\ca-api-proxy" `
-Name processModel.identityType `
-Value 3 # SpecificUser
Set-ItemProperty "IIS:\AppPools\ca-api-proxy" `
-Name processModel.userName `
-Value "DOMAIN\svc-caapi"
Set-ItemProperty "IIS:\AppPools\ca-api-proxy" `
-Name processModel.password `
-Value "YourPassword123!"
# Set.NET version
Set-ItemProperty "IIS:\AppPools\ca-api-proxy" `
-Name managedRuntimeVersion `
-Value "v4.0"步骤 6:强化安全#
按 IP 限制访问(建议)
# Allow only specific IPs (e.g., PKI Trust Manager server)
Add-WebConfigurationProperty `
-Filter "/system.webServer/security/ipSecurity" `
-Name "." `
-Value @{ipAddress="192.168.1.100";subnetMask="255.255.255.255";allowed="true"}
# Deny all others
Set-WebConfigurationProperty `
-Filter "/system.webServer/security/ipSecurity" `
-Name "allowUnlisted" `
-Value "false"⚙️ 配置#
步骤 1:准备 ca 文件夹中的证书文件
⚠️ 重要:证书文件必须放在 C:\Sites\ca-api-proxy\ca\
1. 导出 CA 证书(PEM 格式)
# Export CA certificate from Microsoft CA to ca folder
certutil -ca.cert "C:\Sites\ca-api-proxy\ca\cacert.crt"
# Verify file was created
Test-Path "C:\Sites\ca-api-proxy\ca\cacert.crt"2. 在 ca 文件夹中创建证书链文件
按照以下格式创建 C:\Sites\ca-api-proxy\ca\cachain.crt:
-----BEGIN CERTIFICATE-----
[CA Certificate - Base64 encoded]
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
[Intermediate CA Certificate - Base64 encoded]
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
[Root CA Certificate - Base64 encoded]
-----END CERTIFICATE-----
快速生成证书文件的脚本
# Save as generate-cert-files.ps1
$caFolder = "C:\Sites\ca-api-proxy\ca"
# Export CA certificate
certutil -ca.cert "$caFolder\cacert.crt"
# Export full chain (adjust for your CA hierarchy)
# For a two-tier hierarchy:
$caCert = Get-Content "$caFolder\cacert.crt" -Raw
$rootCert = certutil -root | Select-String "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----" | Out-String
$chain = $caCert + "`n`n" + $rootCert
$chain | Out-File -FilePath "$caFolder\cachain.crt" -Encoding ASCII
Write-Host "Certificate files created in: $caFolder"
Write-Host "- cacert.crt (CA certificate)"
Write-Host "- cachain.crt (Full certificate chain)"步骤 2:获取 CA 配置字符串#
# Open Command Prompt as Administrator
certutil -getconfig
# Output will look like:
# CA\CA-Computer-Name\CA-Name
# Copy this string for web.config步骤 3:配置 web.config#
编辑 C:\Sites\ca-api-proxy\web.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="false" targetFramework="4.7.2" />
<httpRuntime targetFramework="4.7.2" />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
<appSettings>
<!-- CA Configuration string from certutil -getconfig -->
<add key="CAConfig" value="CA\CA-SERVER-NAME\CA-NAME" />
<!-- CA Certificate filename (must be in ca folder) -->
<add key="cacert-filename" value="cacert.crt" />
<!-- Path for log files -->
<add key="LogPath" value="C:\Sites\ca-api-proxy\logs" />
<!-- Optional: Enable debug logging -->
<add key="DebugMode" value="false" />
<!-- Optional: Maximum request size in KB (default: 4096) -->
<add key="MaxRequestSize" value="8192" />
</appSettings>
</configuration>步骤 4:设置 ca 文件夹权限
# Grant full control to service account on the ca folder
icacls "C:\Sites\ca-api-proxy\ca" /grant "svc-caapi:(OI)(CI)F"
# Also grant read permissions to IIS_IUSRS (if needed)
icacls "C:\Sites\ca-api-proxy\ca" /grant "IIS_IUSRS:(OI)(CI)R"步骤 5:重启应用程序#
# Restart application pool
Restart-WebAppPool -Name "ca-api-proxy"
# Or restart IIS
iisreset✅ 测试与验证#
测试 1:验证证书文件位置#
# Check if certificate files are in the correct location
Test-Path "C:\Sites\ca-api-proxy\ca\cacert.crt"
Test-Path "C:\Sites\ca-api-proxy\ca\cachain.crt"
# Check file permissions
icacls "C:\Sites\ca-api-proxy\ca\cacert.crt"
icacls "C:\Sites\ca-api-proxy\ca\cachain.crt"测试 2:API 信息端点#
# Test using PowerShell
$response = Invoke-WebRequest -Uri "http://localhost:9081/" -UseBasicParsing
Write-Host "Status Code:" $response.StatusCode
Write-Host "Response:" $response.Content预期输出应显示 API 版本和可用端点。
测试 3:下载 CA 证书(从 ca 文件夹)#
# This endpoint reads from C:\Sites\ca-api-proxy\ca\cacert.crt
Invoke-WebRequest -Uri "http://localhost:9081/cacert" `
-OutFile "C:\temp\ca-certificate.crt"
# Verify the file matches what's in the ca folder
$apiCert = Get-Content "C:\temp\ca-certificate.crt" -Raw
$caFolderCert = Get-Content "C:\Sites\ca-api-proxy\ca\cacert.crt" -Raw
$apiCert -eq $caFolderCert测试 4:下载完整 CA 链(从 ca 文件夹)#
# This endpoint reads from C:\Sites\ca-api-proxy\ca\cachain.crt
Invoke-WebRequest -Uri "http://localhost:9081/cachain" `
-OutFile "C:\temp\ca-chain.pem"
# Count certificates in chain
$chain = Get-Content "C:\temp\ca-chain.pem"
($chain | Select-String "BEGIN CERTIFICATE").Count测试 5:检查应用程序日志#
# Check if logs are being created
Get-ChildItem "C:\Sites\ca-api-proxy\logs" -Filter "*.log" |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
# View the latest log
$latestLog = Get-ChildItem "C:\Sites\ca-api-proxy\logs" -Filter "*.log" |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
Get-Content $latestLog.FullName -Tail 20🔌 与 PKI Trust Manager 集成#
配置 PKI Trust Manager#
在 PKI Trust Manager 中转到 Integrations → Certification Authorities:
- CA Type:选择“Microsoft Enterprise CA”。
- Proxy URL:
http://ca-api-server:9081/。 - Name:CA 名称。
🐛 故障排除#
常见问题与解决方法
问题 1:“CA Certificate file not found”
错误:应用程序在 ca 文件夹中找不到 cacert.crt。
# Fix: Verify file location and permissions
Test-Path "C:\Sites\ca-api-proxy\ca\cacert.crt"
# Fix: Check web.config - cacert-filename should be "cacert.crt"
Get-Content "C:\Sites\ca-api-proxy\web.config" | Select-String "cacert-filename"问题 2:“Access denied to ca folder”
错误:服务帐户无法读取证书文件。
# Fix: Grant explicit permissions
icacls "C:\Sites\ca-api-proxy\ca" /grant "svc-caapi:(OI)(CI)F"
icacls "C:\Sites\ca-api-proxy\ca\cacert.crt" /grant "svc-caapi:F"
icacls "C:\Sites\ca-api-proxy\ca\cachain.crt" /grant "svc-caapi:F"问题 3:CA 配置字符串不正确
错误:无法连接到 Microsoft CA。
# Fix: Get correct CA configuration string
certutil -getconfig
# Update web.config with the correct value
# Format: CA\Server-Name\CA-Name问题 4:证书文件格式不正确
错误:无法解析证书文件。
# Fix: Ensure files are in PEM format
# Check first line of cacert.crt
Get-Content "C:\Sites\ca-api-proxy\ca\cacert.crt" -First 1
# Should show: -----BEGIN CERTIFICATE-----诊断命令
# Check all prerequisites
Write-Host "=== CA-API Proxy Diagnostic Check ==="
# 1. Check ca folder exists
Write-Host "1. CA Folder: " -NoNewline
if (Test-Path "C:\Sites\ca-api-proxy\ca") {
Write-Host "✓ Exists" -ForegroundColor Green
} else {
Write-Host "✗ Missing!" -ForegroundColor Red
}
# 2. Check certificate files
Write-Host "2. cacert.crt: " -NoNewline
if (Test-Path "C:\Sites\ca-api-proxy\ca\cacert.crt") {
Write-Host "✓ Exists" -ForegroundColor Green
} else {
Write-Host "✗ Missing!" -ForegroundColor Red
}
Write-Host "3. cachain.crt: " -NoNewline
if (Test-Path "C:\Sites\ca-api-proxy\ca\cachain.crt") {
Write-Host "✓ Exists" -ForegroundColor Green
} else {
Write-Host "✗ Missing!" -ForegroundColor Red
}
# 3. Check web.config
Write-Host "4. web.config: " -NoNewline
if (Test-Path "C:\Sites\ca-api-proxy\web.config") {
Write-Host "✓ Exists" -ForegroundColor Green
} else {
Write-Host "✗ Missing!" -ForegroundColor Red
}
# 4. Check IIS site
Write-Host "5. IIS Site: " -NoNewline
if (Get-Website -Name "ca-api-proxy" -ErrorAction SilentlyContinue) {
Write-Host "✓ Running" -ForegroundColor Green
} else {
Write-Host "✗ Not found!" -ForegroundColor Red
}🔒 Buenas prácticas de seguridad#
1. Seguridad de archivos de certificado#
- Mantenga los certificados solo en la carpeta
ca. - Revise periódicamente los permisos de la carpeta
ca. - Supervise intentos de acceso no autorizado.
- Proteja las copias de seguridad de los certificados.
2. Seguridad de red#
- Despliegue solo en una red interna.
- Restrinja el acceso por IP para permitir únicamente PKI Trust Manager.
- Considere HTTPS (requiere certificado SSL en IIS).
3. Seguridad de la cuenta de servicio#
- Utilice una cuenta de servicio dedicada.
- Cambie periódicamente la contraseña.
- Supervise el uso de la cuenta en los registros de seguridad.
- Aplique el principio de privilegio mínimo.
4. Seguridad del sistema de archivos#
# Set restrictive permissions on ca folder
icacls "C:\Sites\ca-api-proxy\ca" /inheritance:r
icacls "C:\Sites\ca-api-proxy\ca" /grant "svc-caapi:(OI)(CI)R"
icacls "C:\Sites\ca-api-proxy\ca" /grant "Administrators:(OI)(CI)F"📊 Endpoints de API#
| Endpoint | Método | Descripción | Autenticación |
|---|---|---|---|
/ | GET | Información y comprobación de estado de la API | Ninguna |
/cacert | GET | Descargar certificado CA desde ca\cacert.crt | Windows Auth |
/cachain | GET | Descargar cadena CA completa desde ca\cachain.crt | Windows Auth |
/templates | GET | Enumerar plantillas de certificado disponibles | Windows Auth |
/issue | POST | Emitir un certificado | Windows Auth |
/renew | POST | Renovar un certificado existente | Windows Auth |
/revoke | POST | Revocar un certificado | Windows Auth |
/status/{requestId} | GET | Consultar estado del certificado | Windows Auth |
/download/{certId} | GET | Descargar certificado emitido | Windows Auth |
🔄 Mantenimiento#
Tareas periódicas#
- Actualizaciones de certificados: actualice
ca\cacert.crtyca\cachain.crtcuando se renueve el certificado CA. - Rotación de registros: configure la rotación de registros de IIS y de la aplicación.
- Actualizaciones de seguridad: aplique los parches de seguridad de Windows y .NET.
- Auditorías de permisos: revise periódicamente los permisos de las carpetas.
Actualizar los archivos del certificado CA#
# Script to update certificate files
$caFolder = "C:\Sites\ca-api-proxy\ca"
# Stop application pool
Stop-WebAppPool -Name "ca-api-proxy"
# Backup old certificates
Copy-Item "$caFolder\cacert.crt" "$caFolder\cacert.crt.backup_$(Get-Date -Format 'yyyyMMdd')"
Copy-Item "$caFolder\cachain.crt" "$caFolder\cachain.crt.backup_$(Get-Date -Format 'yyyyMMdd')"
# Export new CA certificate
certutil -ca.cert "$caFolder\cacert.crt"
# Update chain file (adjust as needed)
# ... generate new cachain.crt ...
# Start application pool
Start-WebAppPool -Name "ca-api-proxy"Script de copia de seguridad#
# backup-ca-api.ps1
$backupDir = "D:\Backups\ca-api-proxy\$(Get-Date -Format 'yyyyMMdd')"
New-Item -ItemType Directory -Path $backupDir -Force
# Backup critical files
Copy-Item "C:\Sites\ca-api-proxy\web.config" -Destination "$backupDir\"
Copy-Item "C:\Sites\ca-api-proxy\ca\" -Destination "$backupDir\ca\" -Recurse
Copy-Item "C:\Sites\ca-api-proxy\logs\" -Destination "$backupDir\logs\" -Recurse📞 Soporte#
Recopilar registros para soporte#
# Collect troubleshooting data
$zipFile = "C:\Temp\ca-api-troubleshoot-$(Get-Date -Format 'yyyyMMdd-HHmm').zip"
# Include ca folder contents
Compress-Archive `
-Path "C:\Sites\ca-api-proxy\ca\*", `
"C:\Sites\ca-api-proxy\logs\*", `
"C:\Sites\ca-api-proxy\web.config" `
-DestinationPath $zipFile
Write-Host "Troubleshooting package created: $zipFile"Información de contacto#
- Correo de soporte: [email protected]
- Documentación: https://securetron.net/documentation
📝 Comandos de referencia rápida#
# Essential commands
# 1. Restart application
Restart-WebAppPool -Name "ca-api-proxy"
# 2. Check certificate files
dir C:\Sites\ca-api-proxy\ca\
# 3. Test endpoints
curl http://localhost:9081/cacert
# 4. View logs
Get-ChildItem C:\Sites\ca-api-proxy\logs\*.log | Sort LastWriteTime | Select -Last 1 | Get-Content -Tail 50
# 5. Verify CA connection
certutil -ping -config "CA\SERVER-NAME\CA-NAME"Puntos clave:
- Los archivos de certificado DEBEN estar en
C:\Sites\ca-api-proxy\ca\. - Se requieren dos archivos:
cacert.crtycachain.crt. - La cuenta de servicio debe poder leer la carpeta
ca. - La cadena de configuración de CA en
web.configdebe ser correcta.
Tiempo de despliegue: ~30 minutos
Seguridad: Windows Authentication + restricciones IP
Compatibilidad: Microsoft CA (Enterprise/Standalone)
Integración: REST API para PKI Trust Manager