Files
certctl/docs/connector-iis.md
T
claude b1ff59dbf2 docs: deployment vendor matrix + per-connector deep-dive docs (NGINX + K8s + IIS + Apache + F5)
Phase 14 of the deploy-hardening II master bundle. The procurement-
team headline doc + per-connector operator guides for the top 5
most-deployed connectors.

NEW docs/deployment-vendor-matrix.md (~30 rows):
- Per (connector × vendor-version) status: ✓ / CI / mock / pending / n/a
- Known issues + workarounds + e2e test name reference
- LTS + current-stable scope per frozen decision 0.1
- Quarterly re-pin cadence guidance for sidecar digests
- "How to add a new vendor version" recipe

Per frozen decision 0.14: a (connector × vendor-version) cell is
"verified" only when ALL apply: ≥1 happy-path e2e green; ≥1
specific-quirk test green for that version; operator manual smoke
completed at least once. Cells lacking the third criterion show
"CI" status (auto-tests green but pending operator validation).

Status snapshot at bundle close:
- NGINX 1.25 + 1.27: CI
- Apache 2.4: CI
- HAProxy 2.6 + 2.8 + 3.0: CI
- Traefik 2.x + 3.x: CI
- Caddy 2.x: CI
- Envoy 1.30 + 1.32: CI (file-mode SDS only; gRPC SDS V3-Pro)
- Postfix 3.6 + 3.8: CI
- Dovecot 2.3: CI
- IIS 10 (2019, 2022): pending (Windows-host-only CI)
- F5 v15.1 + v17.0 + v17.5: mock (real-F5 vagrant box documented)
- SSH OpenSSH 8.x + 9.x: CI
- WinCertStore (2019, 2022): pending (Windows-host-only)
- JavaKeystore JDK 11 + 17 + 21: pending
- K8s 1.28 + 1.30 + 1.31: CI

NEW per-connector deep-dive docs:
- docs/connector-nginx.md (~150 lines, 10 quirks documented)
- docs/connector-k8s.md (~110 lines, 10 quirks)
- docs/connector-iis.md (~120 lines, 10 quirks; Windows-host-only
  CI constraint loud)
- docs/connector-apache.md (~80 lines, 10 quirks)
- docs/connector-f5.md (~190 lines, 10 quirks; two-tier validation
  recipe for operator-supplied real-F5 vagrant box)

Each doc follows the same structure:
- Overview
- Vendor versions tested
- Per-quirk operator guidance (one section per
  TestVendorEdge_<vendor>_<edge>_E2E)
- Troubleshooting matrix
- V3-Pro deferrals
- Related docs cross-refs

Other connector docs (HAProxy, Traefik, Caddy, Envoy, Postfix,
Dovecot, SSH, WinCertStore, JavaKeystore) live in docs/connectors.md
+ are referenced from the matrix.

Phase 15 next: per-vendor CI matrix job in
.github/workflows/ci.yml.
2026-04-30 16:16:48 +00:00

4.4 KiB

Microsoft IIS Connector — Operator Deep-Dive

Per Phase 14 of the deploy-hardening II master bundle.

Overview

The IIS connector (internal/connector/target/iis/) deploys TLS certs to Windows IIS servers via PowerShell (Import-PfxCertificate

  • New-WebBinding + SNI binding). Pre-deploy snapshot of the existing thumbprint allows rollback if the new binding fails.

Vendor versions tested

  • Windows Server 2019 with IIS 10
  • Windows Server 2022 with IIS 10

CI runner constraint

Per frozen decision 0.4: Windows containers run only on Windows hosts. Linux CI runners CAN'T run the IIS sidecar. IIS e2e tests run on a separate windows-vendor-e2e GitHub Actions matrix job on windows-latest runners. Operators on Linux-only CI use //go:build integration && !no_iis to skip.

Per-quirk operator guidance

App-pool recycle (opt-in)

TestVendorEdge_IIS_AppPoolRecycle_OptInForCertChange_E2E

By default, IIS picks up new SSL bindings without app-pool recycle (the binding-edit path is hot). Some sites need recycle to fully reload (e.g., apps that cache cert handles).

Operator action: set AppPoolRecycle: true per-target. The connector then runs Restart-WebAppPool <pool> after binding update.

SNI multi-binding per site

TestVendorEdge_IIS_SNIMultiBindingPerSite_DeployUpdatesCorrectBinding_E2E

When a site has multiple SNI bindings (different hostnames on the same site), connector targets the binding matching the operator-supplied hostname. Other bindings unchanged.

CCS (Centralized Certificate Store)

TestVendorEdge_IIS_CCSCentralizedCertStoreVariant_DeployToSharedStore_E2E

CCS is the file-based variant where multiple IIS servers share a UNC path of cert files. Connector writes to the shared path; all IIS servers pick it up automatically.

WinRM remote vs local PowerShell

TestVendorEdge_IIS_WinRMRemotePath_vs_LocalPowerShellPath_BothWork_E2E

Two code paths produce equivalent cert installs:

  • WinRMHost: "" → local PowerShell (agent runs on the IIS server)
  • WinRMHost: "iis.example" → remote PowerShell via WinRM

Both rotate the same way. WinRM path requires network reachability to port 5985/5986.

Server 2019 vs 2022 PowerShell compat

TestVendorEdge_IIS_WindowsServer2019_vs_2022_PowerShellCompat_E2E

Import-PfxCertificate + New-WebBinding semantics are stable across server versions. PowerShell 5.1 (2019) + PowerShell 7.x (2022) both work.

Friendly name

TestVendorEdge_IIS_FriendlyNameUpdatedOnRotation_E2E

Connector preserves operator-supplied FriendlyName on the cert across rotation. Useful for IIS GUI identification.

HTTP/2 + ALPN

TestVendorEdge_IIS_HTTP2ALPNPreserved_E2E

IIS h2 negotiation preserved across cert rotation. The netsh http show sslcert ALPN attribute survives the binding swap.

Binding-type validation

TestVendorEdge_IIS_BindingTypeHttpsValidated_E2E

Connector refuses to deploy to non-https bindings (e.g., http, net.tcp). Surfaces actionable error.

ARR reverse-proxy

TestVendorEdge_IIS_ARRReverseProxyCertRotation_E2E

Sites using Application Request Routing as reverse proxy: cert rotation does not invalidate ARR routes. The cert-binding edit is independent of the ARR config.

Atomic SNI binding swap

TestVendorEdge_IIS_RemovePreviousBindingOnRotate_E2E

Connector removes the previous SNI binding BEFORE inserting the new one (atomicity at the IIS API level). Prevents brief window where two bindings serve different certs for the same hostname.

Troubleshooting matrix

Symptom Test name Operator action
Cert installed but app pool serving old cert AppPoolRecycle_OptInForCertChange_E2E set AppPoolRecycle: true
Wrong SNI binding updated SNIMultiBindingPerSite_E2E verify hostname selector
Permission denied on cert install n/a agent must run as administrator
WinRM connection failed WinRMRemotePath_vs_LocalPowerShellPath_E2E check WinRM port 5985/5986 reachability
h2 negotiation broken post-rotate HTTP2ALPNPreserved_E2E re-run netsh http add sslcert with appid + clientcertnegotiation=enable

V3-Pro deferrals

  • IIS Application Initialization module integration (warm cert cache after rotation).
  • Azure Key Vault + IIS integration (operator opt-in).