Repository: k3s-io/k3s
File: pkg/cli/cert/cert.go (Go)

Code before:
	Issuer       string
	Usages       []string
	ExpiryTime   time.Time
	ResidualTime time.Duration
	Status       string // "OK", "WARNING", "EXPIRED", "NOT YET VALID"
}

// CertificateInfo defines the structure for storing certificate information
type CertificateInfo struct {
	Certificates []Certificate
}

// getCertUsages returns a slice of strings representing the certificate usages
func getCertUsages(cert *x509.Certificate) []string {
	usages := []string{}
	if cert.IsCA {
		usages = append(usages, "CA")
	}
	for _, eku := range cert.ExtKeyUsage {
		switch eku {
		case x509.ExtKeyUsageServerAuth:
			usages = append(usages, "Server")
		case x509.ExtKeyUsageClientAuth:
			usages = append(usages, "Client")
		}
	}
	if len(usages) == 0 {
		usages = append(usages, "Unknown")
	}
	return usages
}

// collectCertInfo collects information about certificates
func collectCertInfo(controlConfig config.Control, ServicesList []string) (*CertificateInfo, error) {
	result := &CertificateInfo{}
	now := time.Now()
	warn := now.Add(time.Hour * 24 * config.CertificateRenewDays)

	fileMap, err := services.FilesForServices(controlConfig, ServicesList)
	if err != nil {
		return nil, err
	}

	for _, files := range fileMap {
		for _, file := range files {
			certs, err := certutil.CertsFromFile(file)
			if err != nil {
				logrus.Debugf(err.Error())
				continue
			}


Review comment (suggestion):
nit: can you align the checks and output here with the cert monitor checking and event output, wrt the usages list?
https://github.com/k3s-io/k3s/blob/af51c3483a73d4c81b695029190b575953a9a342/pkg/certmonitor/certmonitor.go#L112-L122

I am not sure if IsCA checks the CertSign usage or if there's more to it than that, but we should use consistent values for the usage strings. You might consider moving getCertUsages and/or collectCertInfo into the utils package, so that both the CLI and cert monitor can use it.

Code after:
	Subject      string
	Issuer       string
	Usages       []string
	ExpiryTime   time.Time
	ResidualTime time.Duration
	Status       string // "OK", "WARNING", "EXPIRED", "NOT YET VALID"
}

// CertificateInfo defines the structure for storing certificate information
type CertificateInfo struct {
	Certificates  []Certificate
	ReferenceTime time.Time `json:"-" yaml:"-"`
}

// collectCertInfo collects information about certificates
func collectCertInfo(controlConfig config.Control, ServicesList []string) (*CertificateInfo, error) {
	result := &CertificateInfo{}
	now := time.Now()
	warn := now.Add(time.Hour * 24 * config.CertificateRenewDays)

	fileMap, err := services.FilesForServices(controlConfig, ServicesList)
	if err != nil {
		return nil, err
	}

	for _, files := range fileMap {
		for _, file := range files {
			certs, err := certutil.CertsFromFile(file)
			if err != nil {
				logrus.Debugf("%v", err)
				continue
			}

			for _, cert := range certs {

				expiration := cert.NotAfter
				status := k3sutil.GetCertStatus(cert, now, warn)
				if status == k3sutil.CertStatusNotYetValid {
					expiration = cert.NotBefore
				}
				usages := k3sutil.GetCertUsages(cert)
				result.Certificates = append(result.Certificates, Certificate{
					Filename:     filepath.Base(file),
					Subject:      cert.Subject.CommonName,
					Issuer:       cert.Issuer.CommonName,
					Usages:       usages,
					ExpiryTime:   expiration,
					ResidualTime: cert.NotAfter.Sub(now),
					Status:       status,
				})
			}