From 66985264920ca5f3bdb98167993e3fd0250a391e Mon Sep 17 00:00:00 2001 From: Victor Lyuboslavsky <2685025+getvictor@users.noreply.github.com> Date: Fri, 9 Jan 2026 13:45:35 -0600 Subject: [PATCH] Added validation for empty certificate subject name. (#38114) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Related issue:** Resolves #38109 # Checklist for submitter ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually ## Summary by CodeRabbit * **Bug Fixes** * Improved validation to reject certificate templates with empty or whitespace-only subject names and provide clearer error messaging when the certificate template subject name is required. ✏️ Tip: You can customize this high-level summary in your review settings. (cherry picked from commit cb3f6184c959e1e03305d9bbdb20e813b93ab7fb) --- server/service/certificate_templates_test.go | 22 ++++++++++++++++++++ server/service/certificates.go | 15 +++++++++++++ 2 files changed, 37 insertions(+) diff --git a/server/service/certificate_templates_test.go b/server/service/certificate_templates_test.go index 1d724b6470d..8710bce536a 100644 --- a/server/service/certificate_templates_test.go +++ b/server/service/certificate_templates_test.go @@ -165,6 +165,15 @@ func TestCreateCertificateTemplate(t *testing.T) { }) } }) + + t.Run("Empty or whitespace-only subject name", func(t *testing.T) { + whitespaceSubjectNames := []string{"", " ", " \t\n "} + for _, subjectName := range whitespaceSubjectNames { + _, err := svc.CreateCertificateTemplate(ctx, "my template", TeamID, uint(ValidCATypeID), subjectName) + require.Error(t, err) + require.Contains(t, err.Error(), "Certificate template subject name is required") + } + }) } func TestApplyCertificateTemplateSpecs(t *testing.T) { @@ -365,4 +374,17 @@ func TestApplyCertificateTemplateSpecs(t *testing.T) { require.Error(t, err) require.Contains(t, err.Error(), "Certificate template name is too long") }) + + t.Run("Whitespace-only subject name", func(t *testing.T) { + err := svc.ApplyCertificateTemplateSpecs(ctx, []*fleet.CertificateRequestSpec{ + { + Name: "Template 2", + CertificateAuthorityId: 1, + SubjectName: " ", + }, + }) + require.Error(t, err) + require.Contains(t, err.Error(), "Certificate template subject name is required") + require.Contains(t, err.Error(), "Template 2") + }) } diff --git a/server/service/certificates.go b/server/service/certificates.go index e26bb255c65..63f53ac1699 100644 --- a/server/service/certificates.go +++ b/server/service/certificates.go @@ -22,6 +22,13 @@ const ( // certificateTemplateNameRegex allows only letters, numbers, spaces, dashes, and underscores var certificateTemplateNameRegex = regexp.MustCompile(`^[a-zA-Z0-9 \-_]+$`) +func validateCertificateTemplateSubjectName(subjectName string) error { + if strings.TrimSpace(subjectName) == "" { + return &fleet.BadRequestError{Message: "Certificate template subject name is required."} + } + return nil +} + // validateCertificateTemplateName validates the certificate template name. // Returns a BadRequestError if validation fails. func validateCertificateTemplateName(name string) error { @@ -80,6 +87,10 @@ func (svc *Service) CreateCertificateTemplate(ctx context.Context, name string, return nil, err } + if err := validateCertificateTemplateSubjectName(subjectName); err != nil { + return nil, err + } + if err := validateCertificateTemplateFleetVariables(subjectName); err != nil { return nil, &fleet.BadRequestError{Message: err.Error()} } @@ -425,6 +436,10 @@ func (svc *Service) ApplyCertificateTemplateSpecs(ctx context.Context, specs []* return err } + if err := validateCertificateTemplateSubjectName(spec.SubjectName); err != nil { + return &fleet.BadRequestError{Message: fmt.Sprintf("%s (certificate %s)", err.Error(), spec.Name)} + } + // Get the CA to validate its existence and type. ca, ok := casByID[spec.CertificateAuthorityId] if !ok {