Merge pull request #120064 from SataQiu/feat-kubeadm-20230819
kubeadm: add validation to verify that the CertificateKey is a valid hex encoded AES key
This commit is contained in:
		@@ -17,6 +17,7 @@ limitations under the License.
 | 
				
			|||||||
package validation
 | 
					package validation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/hex"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
	"net/url"
 | 
						"net/url"
 | 
				
			||||||
@@ -54,7 +55,7 @@ func ValidateInitConfiguration(c *kubeadm.InitConfiguration) field.ErrorList {
 | 
				
			|||||||
	allErrs = append(allErrs, ValidateClusterConfiguration(&c.ClusterConfiguration)...)
 | 
						allErrs = append(allErrs, ValidateClusterConfiguration(&c.ClusterConfiguration)...)
 | 
				
			||||||
	// TODO(Arvinderpal): update advertiseAddress validation for dual-stack once it's implemented.
 | 
						// TODO(Arvinderpal): update advertiseAddress validation for dual-stack once it's implemented.
 | 
				
			||||||
	allErrs = append(allErrs, ValidateAPIEndpoint(&c.LocalAPIEndpoint, field.NewPath("localAPIEndpoint"))...)
 | 
						allErrs = append(allErrs, ValidateAPIEndpoint(&c.LocalAPIEndpoint, field.NewPath("localAPIEndpoint"))...)
 | 
				
			||||||
	// TODO: Maybe validate that .CertificateKey is a valid hex encoded AES key
 | 
						allErrs = append(allErrs, ValidateCertificateKey(c.CertificateKey, field.NewPath("certificateKey"))...)
 | 
				
			||||||
	return allErrs
 | 
						return allErrs
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -98,7 +99,7 @@ func ValidateJoinControlPlane(c *kubeadm.JoinControlPlane, fldPath *field.Path)
 | 
				
			|||||||
	allErrs := field.ErrorList{}
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
	if c != nil {
 | 
						if c != nil {
 | 
				
			||||||
		allErrs = append(allErrs, ValidateAPIEndpoint(&c.LocalAPIEndpoint, fldPath.Child("localAPIEndpoint"))...)
 | 
							allErrs = append(allErrs, ValidateAPIEndpoint(&c.LocalAPIEndpoint, fldPath.Child("localAPIEndpoint"))...)
 | 
				
			||||||
		// TODO: Maybe validate that .CertificateKey is a valid hex encoded AES key
 | 
							allErrs = append(allErrs, ValidateCertificateKey(c.CertificateKey, field.NewPath("certificateKey"))...)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return allErrs
 | 
						return allErrs
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -594,6 +595,25 @@ func ValidateAPIEndpoint(c *kubeadm.APIEndpoint, fldPath *field.Path) field.Erro
 | 
				
			|||||||
	return allErrs
 | 
						return allErrs
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidateCertificateKey validates the certificate key is a valid hex encoded AES key
 | 
				
			||||||
 | 
					func ValidateCertificateKey(certificateKey string, fldPath *field.Path) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(certificateKey) > 0 {
 | 
				
			||||||
 | 
							decodedKey, err := hex.DecodeString(certificateKey)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return append(allErrs, field.Invalid(fldPath, certificateKey, fmt.Sprintf("certificate key decoding error: %v", err)))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							k := len(decodedKey)
 | 
				
			||||||
 | 
							if k != constants.CertificateKeySize {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.Invalid(fldPath, certificateKey, fmt.Sprintf("invalid certificate key size %d, the key must be an AES key of size %d", k, constants.CertificateKeySize)))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ValidateIgnorePreflightErrors validates duplicates in:
 | 
					// ValidateIgnorePreflightErrors validates duplicates in:
 | 
				
			||||||
// - ignore-preflight-errors flag and
 | 
					// - ignore-preflight-errors flag and
 | 
				
			||||||
// - ignorePreflightErrors field in {Init,Join}Configuration files.
 | 
					// - ignorePreflightErrors field in {Init,Join}Configuration files.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -455,6 +455,42 @@ func TestValidateAPIEndpoint(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestValidateCertificateKey(t *testing.T) {
 | 
				
			||||||
 | 
						var tests = []struct {
 | 
				
			||||||
 | 
							name           string
 | 
				
			||||||
 | 
							certificateKey string
 | 
				
			||||||
 | 
							expected       bool
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:           "Valid certificate key",
 | 
				
			||||||
 | 
								certificateKey: "e6a2eb8581237ab72a4f494f30285ec12a9694d750b9785706a83bfcbbbd2204",
 | 
				
			||||||
 | 
								expected:       true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:           "Invalid hex encoded string",
 | 
				
			||||||
 | 
								certificateKey: "z6a2eb8581237ab72a4f494f30285ec12a9694d750b9785706a83bfcbbbd2204",
 | 
				
			||||||
 | 
								expected:       false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:           "Invalid AES key size",
 | 
				
			||||||
 | 
								certificateKey: "e6a2",
 | 
				
			||||||
 | 
								expected:       false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, rt := range tests {
 | 
				
			||||||
 | 
							actual := ValidateCertificateKey(rt.certificateKey, nil)
 | 
				
			||||||
 | 
							t.Log(actual)
 | 
				
			||||||
 | 
							if (len(actual) == 0) != rt.expected {
 | 
				
			||||||
 | 
								t.Errorf(
 | 
				
			||||||
 | 
									"%s test case failed:\n\texpected: %t\n\t  actual: %t",
 | 
				
			||||||
 | 
									rt.name,
 | 
				
			||||||
 | 
									rt.expected,
 | 
				
			||||||
 | 
									(len(actual) == 0),
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: Create a separated test for ValidateClusterConfiguration
 | 
					// TODO: Create a separated test for ValidateClusterConfiguration
 | 
				
			||||||
func TestValidateInitConfiguration(t *testing.T) {
 | 
					func TestValidateInitConfiguration(t *testing.T) {
 | 
				
			||||||
	nodename := "valid-nodename"
 | 
						nodename := "valid-nodename"
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user