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 证书。

Architecture Requirements CA Support

🏗️ 架构#

┌─────────────────────────────────────────────────────────┐
│ 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 或更高版本

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 /add

2. 授予 CA 管理权限

  1. 打开 Certification Authority 控制台。
  2. 右键单击 CA 名称 → Properties → Security 选项卡。
  3. 为服务帐户添加以下权限:
    • 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

  1. 打开 Internet Information Services (IIS) Manager。
  2. 右键单击 Sites → Add Website。
  3. 配置:
    • Site name:ca-api-proxy
    • Physical path:C:\Sites\ca-api-proxy
    • Binding:
      • Type:http
      • IP address:All Unassigned(或指定 IP)
      • Port:9081(建议)
      • Host name:留空
  4. 单击 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

  1. 转到 Application Pools。
  2. 找到 ca-api-proxy 池(自动创建)。
  3. 右键单击 → Advanced Settings。
  4. 设置:
    • .NET CLR version:.NET CLR Version v4.0.30319
    • Managed pipeline mode:Integrated
    • Identity:svc-caapi(您的服务帐户)
    • Load User Profile:True

使用 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:

  1. CA Type:选择“Microsoft Enterprise CA”。
  2. Proxy URL:http://ca-api-server:9081/。
  3. 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#

EndpointMétodoDescripciónAutenticación
/GETInformación y comprobación de estado de la APINinguna
/cacertGETDescargar certificado CA desde ca\cacert.crtWindows Auth
/cachainGETDescargar cadena CA completa desde ca\cachain.crtWindows Auth
/templatesGETEnumerar plantillas de certificado disponiblesWindows Auth
/issuePOSTEmitir un certificadoWindows Auth
/renewPOSTRenovar un certificado existenteWindows Auth
/revokePOSTRevocar un certificadoWindows Auth
/status/&#123;requestId&#125;GETConsultar estado del certificadoWindows Auth
/download/&#123;certId&#125;GETDescargar certificado emitidoWindows Auth

🔄 Mantenimiento#

Tareas periódicas#

  1. Actualizaciones de certificados: actualice ca\cacert.crt y ca\cachain.crt cuando se renueve el certificado CA.
  2. Rotación de registros: configure la rotación de registros de IIS y de la aplicación.
  3. Actualizaciones de seguridad: aplique los parches de seguridad de Windows y .NET.
  4. 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#


📝 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:

  1. Los archivos de certificado DEBEN estar en C:\Sites\ca-api-proxy\ca\.
  2. Se requieren dos archivos: cacert.crt y cachain.crt.
  3. La cuenta de servicio debe poder leer la carpeta ca.
  4. La cadena de configuración de CA en web.config debe 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