Closes Rank 5 (Azure half) of the 2026-05-03 Infisical deep-research
deliverable (cowork/infisical-deep-research-results.md Part 5).
Pre-fix, certctl had no path to deploy certs to Azure-managed TLS-
termination endpoints (Application Gateway / Front Door / App Service
/ Container Apps) — operators terminating TLS at Azure had to use
manual `az keyvault certificate import` invocations or external
automation. This commit lands the SDK-driven Azure Key Vault target
connector that closes the gap, mirroring the AWS ACM target shape
shipped in commit 54033aa.
Architecture:
- internal/connector/target/azurekv/azurekv.go — Connector wraps
*azcertificates.Client behind the KeyVaultClient interface seam
(mirrors awsacm's ACMClient + awsacmpca's ACMPCAClient). Lives
in azurekv.go alongside the PFX (PKCS#12) wrapping helper that
bundles the operator-supplied PEM cert + chain + key into the
base64-PFX wire format azcertificates.ImportCertificate accepts.
- internal/connector/target/azurekv/sdk_client.go — SDK-loading
code isolated so the test path (NewWithClient) compiles without
pulling azcore + azidentity transitive deps into the test
binary. DefaultAzureCredential / ManagedIdentityCredential /
EnvironmentCredential / WorkloadIdentityCredential selected via
Config.CredentialMode (closed enum).
- Pre-deploy snapshot via GetCertificate(name, "" /* latest */) so
on-import-failure rollback restores the previous cert. Mirrors
Bundle 5+. The Azure-specific quirk: rollback creates a NEW
VERSION (Key Vault doesn't support version-restore without
soft-delete recovery, which we keep off the minimum-RBAC
surface). Operators reading audit dashboards see e.g. v1=initial,
v2=failed-renewal, v3=rollback-of-v2; the certctl-managed-by +
certctl-certificate-id provenance tags + future certctl-rollback-of
metadata tag let an operator filter rollback artifacts.
- Provenance tags identical to AWS ACM
(certctl-managed-by=certctl + certctl-certificate-id=<mc-id>),
automatically applied on every import. Key Vault carries tags
forward across versions (unlike ACM which strips on re-import),
so no separate AddTags call is required.
- DeploymentRequest.KeyPEM held in agent memory only; PFX wrapping
happens in-memory via software.sslmate.com/src/go-pkcs12. No
disk write.
Tests:
- azurekv_test.go: 13-subtest happy-path + validation matrix —
ValidateConfig (success / missing-vault-url / malformed-vault-
url / missing-cert-name / invalid-credential-mode / reserved-
tag rejection), DeployCertificate (fresh import / rollback-on-
serial-mismatch / empty-key-rejected / no-client-rejected /
SDK-error-surfaced), ValidateOnly (returns sentinel),
ValidateDeployment (serial match / mismatch).
- All tests use the NewWithClient injection seam; no real-Azure
API calls.
- go test -short -count=1 ./internal/connector/target/azurekv/...
green.
Wiring:
- internal/domain/connector.go: TargetTypeAzureKeyVault =
"AzureKeyVault".
- internal/service/target.go: validTargetTypes set extended.
- cmd/agent/main.go::createTargetConnector: AzureKeyVault case
arm mirroring the AWSACM shape exactly.
- cmd/agent/agent_test.go::TestCreateTargetConnector_AllSupported
Types: AzureKeyVault added to the type matrix + the InvalidJSON
matrix (16 supported target types now, up from 15).
go.mod / go.sum:
- github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0 (direct).
- github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 (direct).
- github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/
azcertificates v1.4.0 (direct). The deprecated
/keyvault/azcertificates path appears as a transitive indirect
via Microsoft's microsoft-authentication-library-for-go; we use
the new /security/keyvault/ path exclusively.
Documentation:
- docs/connectors.md "Azure Key Vault" section: config table, RBAC
role recipe (off-the-shelf "Key Vault Certificates Officer" or
custom role with 3 data-plane actions), AKS workload-identity /
managed-identity / service-principal / default credential
recipes, atomic-rollback contract + Azure-version semantics
explanation, soft-delete caveat, App Gateway / Front Door
Terraform attachment snippet, threat model carve-outs (no disk
writes, mandatory provenance tags, no long-lived secrets in
Config), 5-bullet procurement checklist crib.
Out of scope (intentional, flagged in V3-Pro forward path):
- Azure Front Door direct-attach (UpdateRoutingConfig — different
Azure RBAC scope).
- App Gateway / App Service auto-bind (V3-Pro auto-attach).
- Soft-delete recovery (acm:RecoverDeletedCertificate-equivalent
requires extra RBAC; V2 keeps minimum-permission surface).
- GCP Certificate Manager (separate cloud, separate connector).
Verified locally:
- gofmt clean.
- go vet ./internal/connector/target/azurekv/...
./internal/domain/... ./internal/service/...
./cmd/agent/... clean.
- go test -short -count=1 ./internal/connector/target/azurekv/...
./cmd/agent/... green (all 16 supported target types
instantiate via the agent factory).
Reference: cowork/infisical-deep-research-results.md Part 5 Rank 5.
Acquisition prompt:
cowork/rank-5-aws-acm-azure-kv-target-adapters-prompt.md.
Companion commit (AWS half): 54033aa.