Commit 668f7f1b 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 db6dd126
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"text/tabwriter"
"time" "time"
"github.com/k3s-io/k3s/pkg/agent/util" "github.com/k3s-io/k3s/pkg/agent/util"
...@@ -92,27 +93,60 @@ func check(app *cli.Context, cfg *cmds.Server) error { ...@@ -92,27 +93,60 @@ func check(app *cli.Context, cfg *cmds.Server) error {
now := time.Now() now := time.Now()
warn := now.Add(time.Hour * 24 * config.CertificateRenewDays) warn := now.Add(time.Hour * 24 * config.CertificateRenewDays)
outFmt := app.String("output")
for service, files := range fileMap { switch outFmt {
logrus.Info("Checking certificates for " + service) case "text":
for _, file := range files { for service, files := range fileMap {
// ignore errors, as some files may not exist, or may not contain certs. logrus.Info("Checking certificates for " + service)
// Only check whatever exists and has certs. for _, file := range files {
certs, _ := certutil.CertsFromFile(file) // ignore errors, as some files may not exist, or may not contain certs.
for _, cert := range certs { // Only check whatever exists and has certs.
if now.Before(cert.NotBefore) { certs, _ := certutil.CertsFromFile(file)
logrus.Errorf("%s: certificate %s is not valid before %s", file, cert.Subject, cert.NotBefore.Format(time.RFC3339)) for _, cert := range certs {
} else if now.After(cert.NotAfter) { if now.Before(cert.NotBefore) {
logrus.Errorf("%s: certificate %s expired at %s", file, cert.Subject, cert.NotAfter.Format(time.RFC3339)) logrus.Errorf("%s: certificate %s is not valid before %s", file, cert.Subject, cert.NotBefore.Format(time.RFC3339))
} else if warn.After(cert.NotAfter) { } else if now.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)) logrus.Errorf("%s: certificate %s expired at %s", file, cert.Subject, cert.NotAfter.Format(time.RFC3339))
} else { } else if warn.After(cert.NotAfter) {
logrus.Infof("%s: certificate %s is ok, expires at %s", file, cert.Subject, cert.NotAfter.Format(time.RFC3339)) 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 return nil
} }
......
...@@ -63,7 +63,11 @@ func NewCertCommands(check, rotate, rotateCA func(ctx *cli.Context) error) cli.C ...@@ -63,7 +63,11 @@ func NewCertCommands(check, rotate, rotateCA func(ctx *cli.Context) error) cli.C
SkipFlagParsing: false, SkipFlagParsing: false,
SkipArgReorder: true, SkipArgReorder: true,
Action: check, Action: check,
Flags: CertRotateCommandFlags, Flags: append(CertRotateCommandFlags, &cli.StringFlag{
Name: "output,o",
Usage: "Format output. Options: text, table",
Value: "text",
}),
}, },
{ {
Name: "rotate", Name: "rotate",
......
...@@ -46,15 +46,15 @@ var _ = Describe("certificate rotation", Ordered, func() { ...@@ -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' '") certHash, err = testutil.RunCommand("md5sum " + tmpdDataDir + "/server/tls/serving-kube-apiserver.crt | cut -f 1 -d' '")
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
}) })
It("stop k3s", func() { It("stops k3s", func() {
Expect(testutil.K3sKillServer(server)).To(Succeed()) Expect(testutil.K3sKillServer(server)).To(Succeed())
}) })
It("certificate rotate", func() { It("rotates certificates", func() {
_, err := testutil.K3sCmd("certificate", "rotate", "-d", tmpdDataDir) _, err := testutil.K3sCmd("certificate", "rotate", "-d", tmpdDataDir)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
}) })
It("start k3s server", func() { It("starts k3s server", func() {
var err error var err error
server2, err = testutil.K3sStartServer(serverArgs...) server2, err = testutil.K3sStartServer(serverArgs...)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
...@@ -64,7 +64,18 @@ var _ = Describe("certificate rotation", Ordered, func() { ...@@ -64,7 +64,18 @@ var _ = Describe("certificate rotation", Ordered, func() {
return testutil.K3sDefaultDeployments() return testutil.K3sDefaultDeployments()
}, "360s", "5s").Should(Succeed()) }, "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 // get md5sum of the CA certs
var err error var err error
caCertHashAfter, err := testutil.RunCommand("md5sum " + tmpdDataDir + "/server/tls/client-ca.crt | cut -f 1 -d' '") 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