mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 21:47:07 +00:00
Merge pull request #77252 from rojkov/rewrite-CreateServiceAccountKeyAndPublicKeyFiles
kubeadm: do unit testing of actual public function
This commit is contained in:
commit
13885bf9fd
@ -39,6 +39,7 @@ go_library(
|
|||||||
"//cmd/kubeadm/app/constants:go_default_library",
|
"//cmd/kubeadm/app/constants:go_default_library",
|
||||||
"//cmd/kubeadm/app/util/pkiutil:go_default_library",
|
"//cmd/kubeadm/app/util/pkiutil:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/util/cert:go_default_library",
|
"//staging/src/k8s.io/client-go/util/cert:go_default_library",
|
||||||
|
"//staging/src/k8s.io/client-go/util/keyutil:go_default_library",
|
||||||
"//vendor/github.com/pkg/errors:go_default_library",
|
"//vendor/github.com/pkg/errors:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
],
|
],
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
certutil "k8s.io/client-go/util/cert"
|
certutil "k8s.io/client-go/util/cert"
|
||||||
|
"k8s.io/client-go/util/keyutil"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
pkiutil "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
|
pkiutil "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
|
||||||
@ -67,27 +68,31 @@ func CreatePKIAssets(cfg *kubeadmapi.InitConfiguration) error {
|
|||||||
// If the sa public/private key files already exists in the target folder, they are used only if evaluated equals; otherwise an error is returned.
|
// If the sa public/private key files already exists in the target folder, they are used only if evaluated equals; otherwise an error is returned.
|
||||||
func CreateServiceAccountKeyAndPublicKeyFiles(certsDir string) error {
|
func CreateServiceAccountKeyAndPublicKeyFiles(certsDir string) error {
|
||||||
klog.V(1).Infoln("creating a new public/private key files for signing service account users")
|
klog.V(1).Infoln("creating a new public/private key files for signing service account users")
|
||||||
saSigningKey, err := NewServiceAccountSigningKey()
|
_, err := keyutil.PrivateKeyFromFile(filepath.Join(certsDir, kubeadmconstants.ServiceAccountPrivateKeyName))
|
||||||
|
if err == nil {
|
||||||
|
// kubeadm doesn't validate the existing certificate key more than this;
|
||||||
|
// Basically, if we find a key file with the same path kubeadm thinks those files
|
||||||
|
// are equal and doesn't bother writing a new file
|
||||||
|
fmt.Printf("[certs] Using the existing %q key\n", kubeadmconstants.ServiceAccountKeyBaseName)
|
||||||
|
return nil
|
||||||
|
} else if !os.IsNotExist(err) {
|
||||||
|
return errors.Wrapf(err, "file %s existed but it could not be loaded properly", kubeadmconstants.ServiceAccountPrivateKeyName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The key does NOT exist, let's generate it now
|
||||||
|
key, err := pkiutil.NewPrivateKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return writeKeyFilesIfNotExist(
|
// Write .key and .pub files to disk
|
||||||
certsDir,
|
fmt.Printf("[certs] Generating %q key and public key\n", kubeadmconstants.ServiceAccountKeyBaseName)
|
||||||
kubeadmconstants.ServiceAccountKeyBaseName,
|
|
||||||
saSigningKey,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewServiceAccountSigningKey generate public/private key pairs for signing service account tokens.
|
if err := pkiutil.WriteKey(certsDir, kubeadmconstants.ServiceAccountKeyBaseName, key); err != nil {
|
||||||
func NewServiceAccountSigningKey() (crypto.Signer, error) {
|
return err
|
||||||
// The key does NOT exist, let's generate it now
|
|
||||||
saSigningKey, err := pkiutil.NewPrivateKey()
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failure while creating service account token signing key")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return saSigningKey, nil
|
return pkiutil.WritePublicKey(certsDir, kubeadmconstants.ServiceAccountKeyBaseName, key.Public())
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateCACertAndKeyFiles generates and writes out a given certificate authority.
|
// CreateCACertAndKeyFiles generates and writes out a given certificate authority.
|
||||||
@ -246,42 +251,6 @@ func writeCertificateFilesIfNotExist(pkiDir string, baseName string, signingCert
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeKeyFilesIfNotExist write a new key to the given path.
|
|
||||||
// If there already is a key file at the given path; kubeadm tries to load it and check if the values in the
|
|
||||||
// existing and the expected key equals. If they do; kubeadm will just skip writing the file as it's up-to-date,
|
|
||||||
// otherwise this function returns an error.
|
|
||||||
func writeKeyFilesIfNotExist(pkiDir string, baseName string, key crypto.Signer) error {
|
|
||||||
|
|
||||||
// Checks if the key exists in the PKI directory
|
|
||||||
if pkiutil.CertOrKeyExist(pkiDir, baseName) {
|
|
||||||
|
|
||||||
// Try to load .key from the PKI directory
|
|
||||||
_, err := pkiutil.TryLoadKeyFromDisk(pkiDir, baseName)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "%s key existed but it could not be loaded properly", baseName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// kubeadm doesn't validate the existing certificate key more than this;
|
|
||||||
// Basically, if we find a key file with the same path kubeadm thinks those files
|
|
||||||
// are equal and doesn't bother writing a new file
|
|
||||||
fmt.Printf("[certs] Using the existing %q key\n", baseName)
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Write .key and .pub files to disk
|
|
||||||
fmt.Printf("[certs] Generating %q key and public key\n", baseName)
|
|
||||||
|
|
||||||
if err := pkiutil.WriteKey(pkiDir, baseName, key); err != nil {
|
|
||||||
return errors.Wrapf(err, "failure while saving %s key", baseName)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := pkiutil.WritePublicKey(pkiDir, baseName, key.Public()); err != nil {
|
|
||||||
return errors.Wrapf(err, "failure while saving %s public key", baseName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeCSRFilesIfNotExist writes a new CSR to the given path.
|
// writeCSRFilesIfNotExist writes a new CSR to the given path.
|
||||||
// If there already is a CSR file at the given path; kubeadm tries to load it and check if it's a valid certificate.
|
// If there already is a CSR file at the given path; kubeadm tries to load it and check if it's a valid certificate.
|
||||||
// otherwise this function returns an error.
|
// otherwise this function returns an error.
|
||||||
|
@ -301,84 +301,65 @@ func TestWriteCSRFilesIfNotExist(t *testing.T) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWriteKeyFilesIfNotExist(t *testing.T) {
|
func TestCreateServiceAccountKeyAndPublicKeyFiles(t *testing.T) {
|
||||||
|
setupKey, err := keyutil.MakeEllipticPrivateKeyPEM()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Can't setup test: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
setupKey, _ := NewServiceAccountSigningKey()
|
tcases := []struct {
|
||||||
key, _ := NewServiceAccountSigningKey()
|
name string
|
||||||
|
setupFunc func(pkiDir string) error
|
||||||
var tests = []struct {
|
expectedErr bool
|
||||||
setupFunc func(pkiDir string) error
|
expectedKey []byte
|
||||||
expectedError bool
|
|
||||||
expectedKey crypto.Signer
|
|
||||||
}{
|
}{
|
||||||
{ // key does not exists > key written
|
{ // key does not exists > key written
|
||||||
expectedKey: key,
|
name: "generate successfully",
|
||||||
},
|
},
|
||||||
{ // key exists > existing key used
|
{ // key exists > existing key used
|
||||||
|
name: "use existing key",
|
||||||
setupFunc: func(pkiDir string) error {
|
setupFunc: func(pkiDir string) error {
|
||||||
return writeKeyFilesIfNotExist(pkiDir, "dummy", setupKey)
|
err := keyutil.WriteKey(filepath.Join(pkiDir, kubeadmconstants.ServiceAccountPrivateKeyName), setupKey)
|
||||||
|
return err
|
||||||
},
|
},
|
||||||
expectedKey: setupKey,
|
expectedKey: setupKey,
|
||||||
},
|
},
|
||||||
{ // some file exists, but it is not a valid key > err
|
{ // some file exists, but it is not a valid key > err
|
||||||
|
name: "empty key",
|
||||||
setupFunc: func(pkiDir string) error {
|
setupFunc: func(pkiDir string) error {
|
||||||
testutil.SetupEmptyFiles(t, pkiDir, "dummy.key")
|
testutil.SetupEmptyFiles(t, pkiDir, kubeadmconstants.ServiceAccountPrivateKeyName)
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
expectedError: true,
|
expectedErr: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
for _, tt := range tcases {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
dir := testutil.SetupTempDir(t)
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
for _, test := range tests {
|
if tt.setupFunc != nil {
|
||||||
// Create temp folder for the test case
|
if err := tt.setupFunc(dir); err != nil {
|
||||||
tmpdir := testutil.SetupTempDir(t)
|
t.Fatalf("error executing setupFunc: %v", err)
|
||||||
defer os.RemoveAll(tmpdir)
|
}
|
||||||
|
|
||||||
// executes setup func (if necessary)
|
|
||||||
if test.setupFunc != nil {
|
|
||||||
if err := test.setupFunc(tmpdir); err != nil {
|
|
||||||
t.Errorf("error executing setupFunc: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// executes create func
|
err := CreateServiceAccountKeyAndPublicKeyFiles(dir)
|
||||||
err := writeKeyFilesIfNotExist(tmpdir, "dummy", key)
|
if (err != nil) != tt.expectedErr {
|
||||||
|
t.Fatalf("expected error: %v, got: %v, error: %v", tt.expectedErr, err != nil, err)
|
||||||
|
} else if tt.expectedErr {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if !test.expectedError && err != nil {
|
resultingKeyPEM, wasGenerated, err := keyutil.LoadOrGenerateKeyFile(filepath.Join(dir, kubeadmconstants.ServiceAccountPrivateKeyName))
|
||||||
t.Errorf("error writeKeyFilesIfNotExist failed when not expected to fail: %v", err)
|
if err != nil {
|
||||||
continue
|
t.Errorf("Can't load created key: %v", err)
|
||||||
} else if test.expectedError && err == nil {
|
} else if wasGenerated {
|
||||||
t.Error("error writeKeyFilesIfNotExist didn't failed when expected")
|
t.Error("The key was not created")
|
||||||
continue
|
} else if tt.expectedKey != nil && !bytes.Equal(resultingKeyPEM, tt.expectedKey) {
|
||||||
} else if test.expectedError || test.expectedKey == nil {
|
t.Error("Non-existing key is used")
|
||||||
continue
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
// asserts expected files are there
|
|
||||||
testutil.AssertFileExists(t, tmpdir, "dummy.key", "dummy.pub")
|
|
||||||
|
|
||||||
// check created key
|
|
||||||
resultingKey, err := pkiutil.TryLoadKeyFromDisk(tmpdir, "dummy")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("failure reading created key: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
resultingKeyPEM, err := keyutil.MarshalPrivateKeyToPEM(resultingKey)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("failure marshaling created key: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedKeyPEM, err := keyutil.MarshalPrivateKeyToPEM(test.expectedKey)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to marshal expected private key: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(resultingKeyPEM, expectedKeyPEM) {
|
|
||||||
t.Error("created key does not match expected key")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user