Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pkg/templates/k3sca_fixes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ func (p *pki) stagedRotateCmd() string {

func TestRotateCmdForcesWhenTheOldRootCannotVouch(t *testing.T) {
noBC := filepath.Join(t.TempDir(), "no-ext.cnf")
write(t, noBC, "[req]\ndistinguished_name=dn\nprompt=no\n[dn]\nCN=teknoir.ai\n")
write(t, noBC, "[req]\ndistinguished_name=dn\nprompt=no\nx509_extensions=ext\n[dn]\nCN=teknoir.ai\n[ext]\nsubjectKeyIdentifier=hash\n")
future := time.Now().Add(48 * time.Hour).UTC().Format("20060102150405Z")
for _, tc := range []struct {
name string
Expand Down
65 changes: 65 additions & 0 deletions pkg/templates/k3sca_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package templates
import (
"bytes"
"crypto"
"crypto/rand"
"crypto/sha256"
"crypto/x509"
"encoding/hex"
Expand Down Expand Up @@ -133,15 +134,79 @@ func newPKI(t *testing.T) *pki {
func (p *pki) legacyCert() { p.legacyCertArgs() }

// legacyCertArgs adds openssl req arguments, e.g. -addext keyUsage=... for the device-controller kind.
//
// -not_before/-not_after need OpenSSL >= 3.4, so they are stripped and applied by re-signing with Go.
func (p *pki) legacyCertArgs(extra ...string) {
p.t.Helper()
var nb, na string
var kept []string
for i := 0; i < len(extra); i++ {
switch {
case extra[i] == "-not_before" && i+1 < len(extra):
nb = extra[i+1]
i++
case extra[i] == "-not_after" && i+1 < len(extra):
na = extra[i+1]
i++
default:
kept = append(kept, extra[i])
}
}
extra = kept
args := []string{"req", "-x509", "-nodes", "-newkey", "rsa:2048",
"-keyout", filepath.Join(p.cfg, "rsa_private.pem"), "-out", filepath.Join(p.cfg, "rsa_public.pem"),
"-days", "365", "-subj", "/C=US/ST=Texas/L=SHouston/O=Teknoir LLC/CN=teknoir.ai", "-sha256", "-batch"}
cmd := exec.Command("openssl", append(args, extra...)...)
if out, err := cmd.CombinedOutput(); err != nil {
p.t.Fatalf("openssl req: %v\n%s", err, out)
}
if nb != "" || na != "" {
p.resignWithDates(nb, na)
}
}

// resignWithDates re-issues rsa_public.pem (self-signed) with another validity window, same key and subject.
func (p *pki) resignWithDates(nb, na string) {
p.t.Helper()
certPath := filepath.Join(p.cfg, "rsa_public.pem")
c := readCerts(p.t, certPath)[0]
kb, err := os.ReadFile(filepath.Join(p.cfg, "rsa_private.pem"))
if err != nil {
p.t.Fatal(err)
}
blk, _ := pem.Decode(kb)
var key crypto.Signer
if k, err := x509.ParsePKCS8PrivateKey(blk.Bytes); err == nil {
key = k.(crypto.Signer)
} else if k, err := x509.ParsePKCS1PrivateKey(blk.Bytes); err == nil {
key = k
} else {
p.t.Fatal("cannot parse the test private key")
}
parse := func(v string, def time.Time) time.Time {
if v == "" {
return def
}
tm, err := time.Parse("20060102150405Z", v)
if err != nil {
p.t.Fatal(err)
}
return tm
}
tpl := &x509.Certificate{
SerialNumber: c.SerialNumber, Subject: c.Subject,
NotBefore: parse(nb, c.NotBefore), NotAfter: parse(na, c.NotAfter),
KeyUsage: c.KeyUsage, BasicConstraintsValid: c.BasicConstraintsValid, IsCA: c.IsCA,
MaxPathLen: c.MaxPathLen, MaxPathLenZero: c.MaxPathLenZero,
SubjectKeyId: c.SubjectKeyId,
}
der, err := x509.CreateCertificate(rand.Reader, tpl, tpl, key.Public(), key)
if err != nil {
p.t.Fatal(err)
}
if err := os.WriteFile(certPath, pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: der}), 0o644); err != nil {
p.t.Fatal(err)
}
}

// sh runs script with the bootstrap script shell options and the library sourced.
Expand Down
Loading