Commit f31b3d37 authored by Derek Nola's avatar Derek Nola

Add "k3s certificate check" clause for better test coverage (#11485)

* Add "k3s certificate check" clause for better test coverage Signed-off-by: 's avatarDerek Nola <derek.nola@suse.com> * Add table support to cert check Signed-off-by: 's avatarDerek Nola <derek.nola@suse.com> --------- Signed-off-by: 's avatarDerek Nola <derek.nola@suse.com>
parent 39f4cbb3
......@@ -6,6 +6,7 @@ import (
"os"
"path/filepath"
"strings"
"text/tabwriter"
"time"
"github.com/k3s-io/k3s/pkg/agent/util"
......@@ -92,27 +93,60 @@ func check(app *cli.Context, cfg *cmds.Server) error {
now := time.Now()
warn := now.Add(time.Hour * 24 * config.CertificateRenewDays)
for service, files := range fileMap {
logrus.Info("Checking certificates for " + service)
for _, file := range files {
// ignore errors, as some files may not exist, or may not contain certs.
// Only check whatever exists and has certs.
certs, _ := certutil.CertsFromFile(file)
for _, cert := range certs {
if now.Before(cert.NotBefore) {
logrus.Errorf("%s: certificate %s is not valid before %s", file, cert.Subject, cert.NotBefore.Format(time.RFC3339))
} else if now.After(cert.NotAfter) {
logrus.Errorf("%s: certificate %s expired at %s", file, cert.Subject, cert.NotAfter.Format(time.RFC3339))
} else if warn.After(cert.NotAfter) {
logrus.Warnf("%s: certificate %s will expire within %d days at %s", file, cert.Subject, config.CertificateRenewDays, cert.NotAfter.Format(time.RFC3339))
} else {
logrus.Infof("%s: certificate %s is ok, expires at %s", file, cert.Subject, cert.NotAfter.Format(time.RFC3339))
outFmt := app.String("output")
switch outFmt {
case "text":
for service, files := range fileMap {
logrus.Info("Checking certificates for " + service)
for _, file := range files {
// ignore errors, as some files may not exist, or may not contain certs.
// Only check whatever exists and has certs.
certs, _ := certutil.CertsFromFile(file)
for _, cert := range certs {
if now.Before(cert.NotBefore) {
logrus.Errorf("%s: certificate %s is not valid before %s", file, cert.Subject, cert.NotBefore.Format(time.RFC3339))
} else if now.After(cert.NotAfter) {
logrus.Errorf("%s: certificate %s expired at %s", file, cert.Subject, cert.NotAfter.Format(time.RFC3339))
} else if warn.After(cert.NotAfter) {
logrus.Warnf("%s: certificate %s will expire within %d days at %s", file, cert.Subject, config.CertificateRenewDays, cert.NotAfter.Format(time.RFC3339))
} else {
logrus.Infof("%s: certificate %s is ok, expires at %s", file, cert.Subject, cert.NotAfter.Format(time.RFC3339))
}
}
}
}
case "table":
var tabBuffer bytes.Buffer
w := tabwriter.NewWriter(&tabBuffer, 0, 0, 2, ' ', 0)
fmt.Fprintf(w, "\n")
fmt.Fprintf(w, "CERTIFICATE\tSUBJECT\tSTATUS\tEXPIRES\n")
fmt.Fprintf(w, "-----------\t-------\t------\t-------")
for _, files := range fileMap {
for _, file := range files {
certs, _ := certutil.CertsFromFile(file)
for _, cert := range certs {
baseName := filepath.Base(file)
var status string
expiration := cert.NotAfter.Format(time.RFC3339)
if now.Before(cert.NotBefore) {
status = "NOT YET VALID"
expiration = cert.NotBefore.Format(time.RFC3339)
} else if now.After(cert.NotAfter) {
status = "EXPIRED"
} else if warn.After(cert.NotAfter) {
status = "WARNING"
} else {
status = "OK"
}
fmt.Fprintf(w, "\n%s\t%s\t%s\t%s", baseName, cert.Subject, status, expiration)
}
}
}
w.Flush()
fmt.Println(tabBuffer.String())
default:
return fmt.Errorf("invalid output format %s", outFmt)
}
return nil
}
......
......@@ -63,7 +63,11 @@ func NewCertCommands(check, rotate, rotateCA func(ctx *cli.Context) error) cli.C
SkipFlagParsing: false,
SkipArgReorder: true,
Action: check,
Flags: CertRotateCommandFlags,
Flags: append(CertRotateCommandFlags, &cli.StringFlag{
Name: "output,o",
Usage: "Format output. Options: text, table",
Value: "text",
}),
},
{
Name: "rotate",
......
......@@ -46,15 +46,15 @@ var _ = Describe("certificate rotation", Ordered, func() {
certHash, err = testutil.RunCommand("md5sum " + tmpdDataDir + "/server/tls/serving-kube-apiserver.crt | cut -f 1 -d' '")
Expect(err).ToNot(HaveOccurred())
})
It("stop k3s", func() {
It("stops k3s", func() {
Expect(testutil.K3sKillServer(server)).To(Succeed())
})
It("certificate rotate", func() {
It("rotates certificates", func() {
_, err := testutil.K3sCmd("certificate", "rotate", "-d", tmpdDataDir)
Expect(err).ToNot(HaveOccurred())
})
It("start k3s server", func() {
It("starts k3s server", func() {
var err error
server2, err = testutil.K3sStartServer(serverArgs...)
Expect(err).ToNot(HaveOccurred())
......@@ -64,7 +64,18 @@ var _ = Describe("certificate rotation", Ordered, func() {
return testutil.K3sDefaultDeployments()
}, "360s", "5s").Should(Succeed())
})
It("get certificate hash", func() {
It("checks the certificate status", func() {
res, err := testutil.K3sCmd("certificate", "check", "-d", tmpdDataDir)
Expect(err).ToNot(HaveOccurred())
for i, line := range strings.Split(res, "\n") {
// First line is just server info
if i == 0 || line == "" {
continue
}
Expect(line).To(MatchRegexp("certificate.*is ok|Checking certificates"), res)
}
})
It("gets certificate hash", func() {
// get md5sum of the CA certs
var err error
caCertHashAfter, err := testutil.RunCommand("md5sum " + tmpdDataDir + "/server/tls/client-ca.crt | cut -f 1 -d' '")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment