kubeadm: avoid panic in TryLoadPrivatePublicKeyFromDisk for mismatched private/public key types

This commit is contained in:
SataQiu 2026-05-10 18:08:46 +08:00
parent f1e0a3bfad
commit ecd29dbef8
2 changed files with 82 additions and 2 deletions

View file

@ -340,11 +340,20 @@ func TryLoadPrivatePublicKeyFromDisk(pkiPath, name string) (crypto.PrivateKey, c
}
// Allow RSA and ECDSA formats only
mismatchErrFmt := "the private key file %[2]s is in %[1]s format but the public key file %[3]s is not in %[1]s format"
switch k := privKey.(type) {
case *rsa.PrivateKey:
return k, pubKeys[0].(*rsa.PublicKey), nil
pubKey, ok := pubKeys[0].(*rsa.PublicKey)
if !ok {
return nil, nil, errors.Errorf(mismatchErrFmt, "RSA", privateKeyPath, publicKeyPath)
}
return k, pubKey, nil
case *ecdsa.PrivateKey:
return k, pubKeys[0].(*ecdsa.PublicKey), nil
pubKey, ok := pubKeys[0].(*ecdsa.PublicKey)
if !ok {
return nil, nil, errors.Errorf(mismatchErrFmt, "ECDSA", privateKeyPath, publicKeyPath)
}
return k, pubKey, nil
default:
return nil, nil, errors.Errorf("the private key file %s is neither in RSA nor ECDSA format", privateKeyPath)
}

View file

@ -566,6 +566,77 @@ func TestTryLoadKeyFromDisk(t *testing.T) {
}
}
func TestTryLoadPrivatePublicKeyFromDisk(t *testing.T) {
tests := []struct {
desc string
privateKey crypto.Signer
publicKey crypto.PublicKey
writePub bool
wantErr bool
}{
{
desc: "RSA private key and RSA public key",
privateKey: rootCAKey,
publicKey: rootCAKey.Public(),
writePub: true,
wantErr: false,
},
{
desc: "ECDSA private key and ECDSA public key",
privateKey: ecdsaP256Key,
publicKey: ecdsaP256Key.Public(),
writePub: true,
wantErr: false,
},
{
desc: "RSA private key and ECDSA public key",
privateKey: rootCAKey,
publicKey: ecdsaP256Key.Public(),
writePub: true,
wantErr: true,
},
{
desc: "ECDSA private key and RSA public key",
privateKey: ecdsaP256Key,
publicKey: rootCAKey.Public(),
writePub: true,
wantErr: true,
},
{
desc: "missing public key file",
privateKey: rootCAKey,
writePub: false,
wantErr: true,
},
}
for _, rt := range tests {
t.Run(rt.desc, func(t *testing.T) {
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
t.Fatalf("Couldn't create tmpdir")
}
defer func() { _ = os.RemoveAll(tmpdir) }()
err = WriteKey(tmpdir, "foo", rt.privateKey)
if err != nil {
t.Fatalf("failed to write private key: %v", err)
}
if rt.writePub {
err = WritePublicKey(tmpdir, "foo", rt.publicKey)
if err != nil {
t.Fatalf("failed to write public key: %v", err)
}
}
_, _, actual := TryLoadPrivatePublicKeyFromDisk(tmpdir, "foo")
if (actual != nil) != rt.wantErr {
t.Fatalf("TryLoadPrivatePublicKeyFromDisk() error = %v, wantErr %v", actual, rt.wantErr)
}
})
}
}
func TestPathsForCertAndKey(t *testing.T) {
crtPath, keyPath := PathsForCertAndKey("/foo", "bar")
expectedPath := filepath.FromSlash("/foo/bar.crt")