func ValidateNamedCertificates(fieldName string, namedCertificates []api.NamedCertificate) ValidationResults { validationResults := ValidationResults{} takenNames := sets.NewString() for i, namedCertificate := range namedCertificates { fieldName := fmt.Sprintf("%s[%d]", fieldName, i) certDNSNames := []string{} if len(namedCertificate.CertFile) == 0 { validationResults.AddErrors(fielderrors.NewFieldRequired(fieldName + ".certInfo")) } else if certInfoErrors := ValidateCertInfo(namedCertificate.CertInfo, false); len(certInfoErrors) > 0 { validationResults.AddErrors(certInfoErrors.Prefix(fieldName)...) } else if cert, err := tls.LoadX509KeyPair(namedCertificate.CertFile, namedCertificate.KeyFile); err != nil { validationResults.AddErrors(fielderrors.NewFieldInvalid(fieldName+".certInfo", namedCertificate.CertInfo, fmt.Sprintf("error loading certificate/key: %v", err))) } else { leaf, _ := x509.ParseCertificate(cert.Certificate[0]) certDNSNames = append(certDNSNames, leaf.Subject.CommonName) certDNSNames = append(certDNSNames, leaf.DNSNames...) } if len(namedCertificate.Names) == 0 { validationResults.AddErrors(fielderrors.NewFieldRequired(fieldName + ".names")) } for j, name := range namedCertificate.Names { nameFieldName := fieldName + fmt.Sprintf(".names[%d]", j) if len(name) == 0 { validationResults.AddErrors(fielderrors.NewFieldRequired(nameFieldName)) continue } if takenNames.Has(name) { validationResults.AddErrors(fielderrors.NewFieldInvalid(nameFieldName, name, "this name is already used in another named certificate")) continue } // validate names as domain names or *.*.foo.com domain names validDNSName := true for _, s := range strings.Split(name, ".") { if s != "*" && !kutil.IsDNS1123Label(s) { validDNSName = false } } if !validDNSName { validationResults.AddErrors(fielderrors.NewFieldInvalid(nameFieldName, name, "must be a valid DNS name")) continue } takenNames.Insert(name) // validate certificate has common name or subject alt names that match if len(certDNSNames) > 0 { foundMatch := false for _, dnsName := range certDNSNames { if cmdutil.HostnameMatches(dnsName, name) { foundMatch = true break } } if !foundMatch { validationResults.AddWarnings(fielderrors.NewFieldInvalid(nameFieldName, name, "the specified certificate does not have a CommonName or DNS subjectAltName that matches this name")) } } } } return validationResults }
func ValidateNamedCertificates(fldPath *field.Path, namedCertificates []api.NamedCertificate) ValidationResults { validationResults := ValidationResults{} takenNames := sets.NewString() for i, namedCertificate := range namedCertificates { idxPath := fldPath.Index(i) certDNSNames := []string{} if len(namedCertificate.CertFile) == 0 { validationResults.AddErrors(field.Required(idxPath.Child("certInfo"), "")) } else if certInfoErrors := ValidateCertInfo(namedCertificate.CertInfo, false, idxPath); len(certInfoErrors) > 0 { validationResults.AddErrors(certInfoErrors...) } else if cert, err := tls.LoadX509KeyPair(namedCertificate.CertFile, namedCertificate.KeyFile); err != nil { validationResults.AddErrors(field.Invalid(idxPath.Child("certInfo"), namedCertificate.CertInfo, fmt.Sprintf("error loading certificate/key: %v", err))) } else { leaf, _ := x509.ParseCertificate(cert.Certificate[0]) certDNSNames = append(certDNSNames, leaf.Subject.CommonName) certDNSNames = append(certDNSNames, leaf.DNSNames...) } if len(namedCertificate.Names) == 0 { validationResults.AddErrors(field.Required(idxPath.Child("names"), "")) } for j, name := range namedCertificate.Names { jdxPath := idxPath.Child("names").Index(j) if len(name) == 0 { validationResults.AddErrors(field.Required(jdxPath, "")) continue } if takenNames.Has(name) { validationResults.AddErrors(field.Invalid(jdxPath, name, "this name is already used in another named certificate")) continue } // validate names as domain names or *.*.foo.com domain names validDNSName := true for _, s := range strings.Split(name, ".") { if s != "*" && len(utilvalidation.IsDNS1123Label(s)) != 0 { validDNSName = false } } if !validDNSName { validationResults.AddErrors(field.Invalid(jdxPath, name, "must be a valid DNS name")) continue } takenNames.Insert(name) // validate certificate has common name or subject alt names that match if len(certDNSNames) > 0 { foundMatch := false for _, dnsName := range certDNSNames { if cmdutil.HostnameMatches(dnsName, name) { foundMatch = true break } // if the cert has a wildcard dnsName, and we've configured a non-wildcard name, see if our specified name will match against the dnsName. if strings.HasPrefix(dnsName, "*.") && !strings.HasPrefix(name, "*.") && cmdutil.HostnameMatches(name, dnsName) { foundMatch = true break } } if !foundMatch { validationResults.AddWarnings(field.Invalid(jdxPath, name, "the specified certificate does not have a CommonName or DNS subjectAltName that matches this name")) } } } } return validationResults }