PROBLEM SUMMARY
When using vcert run with a playbook that only specifies commonName in the subject, the policy defaults for Organization, Locality, State, and Country are not applied to the certificate request. The same enrollment via vcert enroll (CLI) correctly picks up all subject defaults from the zone configuration.
STEPS TO REPRODUCE
- Configure a TPP policy or TLSPC Issuing Template with subject defaults (e.g. O=Venafi, L=London, ST=London, C=GB)
- Confirm defaults are returned via
getpolicy
- CLI test — enroll with only CN, no subject flags:
vcert enroll -p vcp -k <apikey> -z "app\template" --cn "test.example.com" --san-dns "test.example.com" --key-size 3072 --cert-file cert.pem
- Playbook test — create a minimal playbook with only commonName:
certificateTasks:
- name: test
request:
zone: "app\\template"
csr: local
keyType: RSA
keySize: 3072
subject:
commonName: "test.example.com"
sanDNS:
- "test.example.com"
installations:
- format: PEM
file: "./output/cert.pem"
- Run
vcert run -f playbook.yaml --force-renew
- Compare certificate subjects from both enrollments
EXPECTED RESULTS
Both CLI and playbook should produce certificates with the same subject, including O, L, ST, C from the policy defaults.
ACTUAL RESULTS
CLI result (correct — all defaults applied):
subject=
countryName = GB
stateOrProvinceName = London
localityName = London
organizationName = Venafi
organizationalUnitName = vcert
commonName = test.example.com
Playbook result (broken — defaults missing):
subject=
organizationalUnitName = vcert
commonName = test.example.com
O, L, ST, C are missing. The OU that appears is enforced server-side by TPP policy / injected by the CA, not applied by vcert.
Same behavior on both TLSPC and TPP.
ENVIRONMENT DETAILS
- vcert v5.12.3 (latest release), pre-built Linux x86_64 binary
- Ubuntu 24.04
- Tested against TLSPC (SaaS) and TPP (self-hosted, 24.x)
COMMENTS/WORKAROUNDS
Workaround: explicitly set all subject fields in the playbook YAML.
The probable root cause is in how the playbook converts its Subject struct to certificate.Request. The playbook Subject in pkg/playbook/app/domain uses string types for O, C, L, ST:
type Subject struct {
Organization string `yaml:"organization,omitempty"`
Country string `yaml:"country,omitempty"`
Locality string `yaml:"locality,omitempty"`
Province string `yaml:"state,omitempty"`
OrgUnits []string `yaml:"orgUnits,omitempty"`
}
But pkix.Name uses []string for these fields. When converting, empty strings likely get wrapped into []string{""} (length 1), so UpdateCertificateRequest()'s check if len(request.Subject.Organization) == 0 sees length 1 and skips applying the default. The CLI doesn't have this problem because unset flags leave those fields as nil/empty slices.
Related: #436
PROBLEM SUMMARY
When using
vcert runwith a playbook that only specifiescommonNamein the subject, the policy defaults for Organization, Locality, State, and Country are not applied to the certificate request. The same enrollment viavcert enroll(CLI) correctly picks up all subject defaults from the zone configuration.STEPS TO REPRODUCE
getpolicyvcert run -f playbook.yaml --force-renewEXPECTED RESULTS
Both CLI and playbook should produce certificates with the same subject, including O, L, ST, C from the policy defaults.
ACTUAL RESULTS
CLI result (correct — all defaults applied):
Playbook result (broken — defaults missing):
O, L, ST, C are missing. The OU that appears is enforced server-side by TPP policy / injected by the CA, not applied by vcert.
Same behavior on both TLSPC and TPP.
ENVIRONMENT DETAILS
COMMENTS/WORKAROUNDS
Workaround: explicitly set all subject fields in the playbook YAML.
The probable root cause is in how the playbook converts its
Subjectstruct tocertificate.Request. The playbookSubjectinpkg/playbook/app/domainusesstringtypes for O, C, L, ST:But
pkix.Nameuses[]stringfor these fields. When converting, empty strings likely get wrapped into[]string{""}(length 1), soUpdateCertificateRequest()'s checkif len(request.Subject.Organization) == 0sees length 1 and skips applying the default. The CLI doesn't have this problem because unset flags leave those fields as nil/empty slices.Related: #436