From 490f55c689a2fa8586bc72d213d24179d776775f Mon Sep 17 00:00:00 2001 From: Ashwin Hendre Date: Tue, 3 Feb 2026 15:48:07 +0530 Subject: [PATCH] Power VS: SSH key must be RSA --- .../installconfig/platformprovisioncheck.go | 5 ++ pkg/asset/installconfig/powervs/validation.go | 19 +++++++ .../installconfig/powervs/validation_test.go | 50 +++++++++++++++++++ 3 files changed, 74 insertions(+) diff --git a/pkg/asset/installconfig/platformprovisioncheck.go b/pkg/asset/installconfig/platformprovisioncheck.go index e49d725b939..b744a879623 100644 --- a/pkg/asset/installconfig/platformprovisioncheck.go +++ b/pkg/asset/installconfig/platformprovisioncheck.go @@ -172,6 +172,11 @@ func (a *PlatformProvisionCheck) Generate(ctx context.Context, dependencies asse if err != nil { return err } + + err = powervsconfig.ValidateSSHKey(ic.Config) + if err != nil { + return err + } case external.Name, none.Name: // no special provisioning requirements to check case nutanix.Name: diff --git a/pkg/asset/installconfig/powervs/validation.go b/pkg/asset/installconfig/powervs/validation.go index 15fb6815be2..1d4806236b4 100644 --- a/pkg/asset/installconfig/powervs/validation.go +++ b/pkg/asset/installconfig/powervs/validation.go @@ -7,6 +7,7 @@ import ( "strings" "time" + "golang.org/x/crypto/ssh" "k8s.io/apimachinery/pkg/util/validation/field" "github.com/openshift/installer/pkg/types" @@ -351,3 +352,21 @@ func ValidateTransitGateway(client API, ic *types.InstallConfig) error { return nil } + +// ValidateSSHKey checks if the SSH key uses the RSA Algorithm. +func ValidateSSHKey(ic *types.InstallConfig) error { + var ( + key ssh.PublicKey + keyType string + err error + ) + key, _, _, _, err = ssh.ParseAuthorizedKey([]byte(ic.SSHKey)) + if err != nil { + return fmt.Errorf("provided ssh public key is not valid: %w", err) + } + keyType = key.Type() + if keyType == "ssh-rsa" { + return nil + } + return fmt.Errorf("unsupported ssh public key type %s. The public key must be of type RSA", keyType) +} diff --git a/pkg/asset/installconfig/powervs/validation_test.go b/pkg/asset/installconfig/powervs/validation_test.go index ad846618f88..cb5d116a18a 100644 --- a/pkg/asset/installconfig/powervs/validation_test.go +++ b/pkg/asset/installconfig/powervs/validation_test.go @@ -113,6 +113,8 @@ var ( ID: &validRG, }, } + validSSHKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDKwDrQ6Rqd3DmVj8FdrcSmJz2KFuRwWhIVFZNNwG9wxcFDAuELrb0iDi6ZcVpB+M5UBsS7W8lZaOxOJ1HuIMrQsxGfOjSLFAQeNP3RbCsb7GsjMXcWae/XH8G5ZREQAQ37e+6jKT1wHlZxDZwFMe1b5BINtDez8vG3O0UeZ5JNPflo2sxU7kHO8ZlR9HPSw3xFRIIzioQsdeiNa+c9lO0tYpQ4VV18NpBuMu/HWknG+3OGeg54TlUOOAsRsLL7i23HCjHlnwKp8uLfnsMATeCHf4jQvke+4fihhbWF1H7fFvTSNuPiPaK9IJ6qwPJs1L8c/H3guvLpzgqgL2QB3g+KfJvj+w2OUoO+l+SvaiULRNLl9s4b7Vpxi3DpBZ+nWe9HzmVYKWNSIMeaojdjr1jsh9V3WLPq2aJxdP5d/8RoDXFjf9q+0yiB9o/sWGgTSVyF6I3TOtdLSdE6Ahy9+beC+2WnN8lLcklIP5ukKfASryQwqRiGkkhFez/MKkVmajk= azuread\ashwinhendre2@DESKTOP-RSR2EUD" + invalidSSHKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBKnZv4Fr3W7TUYd9YNvvGGvkULb6XbsaeB+uJ7zUlrR azuread\ashwinhendre2@DESKTOP-RSR2EUD" regionWithPER = "dal10" regionWithoutPER = "foo99" regionPERUnknown = "bah77" @@ -687,6 +689,54 @@ func TestValidateServiceInstance(t *testing.T) { } } +func TestValidateSSHKey(t *testing.T) { + cases := []struct { + name string + edits editFunctions + errorMsg string + }{ + { + name: "Invalid SSH key specified", + edits: editFunctions{ + func(ic *types.InstallConfig) { + ic.SSHKey = invalidSSHKey + }, + }, + errorMsg: fmt.Sprintf("unsupported ssh public key type %s. The public key must be of type RSA.", "ssh-ed25519"), + }, + { + name: "Valid SSH Key specified", + edits: editFunctions{ + func(ic *types.InstallConfig) { + ic.SSHKey = validSSHKey + }, + }, + errorMsg: "", + }, + } + setMockEnvVars() + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + // Run tests + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + editedInstallConfig := validInstallConfig() + for _, edit := range tc.edits { + edit(editedInstallConfig) + } + + aggregatedErrors := powervs.ValidateSSHKey(editedInstallConfig) + if tc.errorMsg != "" { + assert.Regexp(t, tc.errorMsg, aggregatedErrors) + } else { + assert.NoError(t, aggregatedErrors) + } + }) + } +} + func setMockEnvVars() { os.Setenv("POWERVS_AUTH_FILEPATH", "./tmp/powervs/config.json") os.Setenv("IBMID", "foo")