hashicorp/nomad · error

error generating CA certificate: %s

Error message

error generating CA certificate: %s

What it means

GenerateCA failed at the x509.CreateCertificate step when building the self-signed CA certificate. The crypto/x509 layer rejected the template/signer combination, and the underlying Go error is wrapped into this message. It means the CA could not be minted at all, so no cert or key material is returned.

Source

Thrown at helper/tlsutil/generate.go:195

			CommonName:         opts.Name,
		},
		BasicConstraintsValid: true,
		KeyUsage:              x509.KeyUsageCertSign | x509.KeyUsageCRLSign | x509.KeyUsageDigitalSignature,
		IsCA:                  true,
		NotAfter:              time.Now().AddDate(0, 0, opts.Days),
		NotBefore:             time.Now(),
		AuthorityKeyId:        id,
		SubjectKeyId:          id,
	}

	if len(opts.PermittedDNSDomains) > 0 {
		template.PermittedDNSDomainsCritical = true
		template.PermittedDNSDomains = opts.PermittedDNSDomains
	}
	bs, err := x509.CreateCertificate(
		rand.Reader, &template, &template, signer.Public(), signer)
	if err != nil {
		return "", "", fmt.Errorf("error generating CA certificate: %s", err)
	}

	var buf bytes.Buffer
	err = pem.Encode(&buf, &pem.Block{Type: "CERTIFICATE", Bytes: bs})
	if err != nil {
		return "", "", fmt.Errorf("error encoding private key: %s", err)
	}

	return buf.String(), pk, nil
}

// GenerateCert generates a new certificate for agent TLS (not to be confused with Connect TLS)
func GenerateCert(opts CertOpts) (string, string, error) {
	parent, err := parseCert(opts.CA)
	if err != nil {
		return "", "", err
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Read the wrapped %s detail from x509.CreateCertificate and fix the offending template field (most often the validity window or PermittedDNSDomains).
  2. Ensure opts.Duration is positive so template.NotAfter is after NotBefore.
  3. Verify PermittedDNSDomains entries are valid DNS names (no schemes, wildcards only as leading *.).
  4. Check the signer passed to GenerateCA is a valid ecdsa or rsa key generated with the matching GeneratePrivateKey.
  5. Confirm the host entropy/PRNG is functional (rand.Reader errors are rare but possible).

Example fix

// before
caCert, _, err := tlsutil.GenerateCA(tlsutil.CAOpts{Duration: 0})
// after
caCert, _, err := tlsutil.GenerateCA(tlsutil.CAOpts{Duration: 6 * 30 * 24 * time.Hour})
Defensive patterns

Strategy: validation

Validate before calling

func validCAOpts(o tlsutil.CAOpts) error {
	if o.Duration <= 0 { return fmt.Errorf("CA duration must be positive") }
	for _, d := range o.PermittedDNSDomains {
		if d == "" { return fmt.Errorf("empty permitted DNS domain") }
	}
	switch o.Name {
	case "": return fmt.Errorf("CA name required")
	}
	return nil
}

Try / catch

caCert, pk, err := tlsutil.GenerateCA(opts)
if err != nil {
	if strings.Contains(err.Error(), "error generating CA certificate") {
		return fmt.Errorf("CA template rejected by x509: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling helper/tlsutil.GenerateCA with a template the x509 package rejects: invalid validity window (NotAfter before NotBefore), malformed PermittedDNSDomains with PermittedDNSDomainsCritical=true, unsupported key type for the signer, or rand.Reader failure.

Common situations: Passing zero/negative Duration so NotAfter precedes NotBefore; misconfigured name-constraint domains; generating CAs on systems with a broken entropy source; custom callers building templates with unsupported extensions.

Understand the failure class

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/c8436110f6896ed9. Report an issue: GitHub.