Skip to content

Commit

Permalink
feat(cluster): support normal ssh user with nopassword sudo
Browse files Browse the repository at this point in the history
  • Loading branch information
QianChenglong authored and tke-robot committed Jun 30, 2020
1 parent c373624 commit 48cbf22
Show file tree
Hide file tree
Showing 11 changed files with 352 additions and 216 deletions.
9 changes: 5 additions & 4 deletions api/platform/validation/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"fmt"
"math"
"net"
"strings"
"time"

"k8s.io/apimachinery/pkg/api/errors"
Expand Down Expand Up @@ -137,9 +138,6 @@ func ValidateWorkerTimeOffset(fldPath *field.Path, worker *ssh.SSH, masters []*s
func ValidateSSH(fldPath *field.Path, ip string, port int, user string, password []byte, privateKey []byte, passPhrase []byte) field.ErrorList {
allErrs := field.ErrorList{}

if user != "root" {
allErrs = append(allErrs, field.Invalid(fldPath.Child("user"), user, "must be root"))
}
for _, msg := range validation.IsValidIP(ip) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("ip"), ip, msg))

Expand Down Expand Up @@ -169,10 +167,13 @@ func ValidateSSH(fldPath *field.Path, ip string, port int, user string, password
if err != nil {
allErrs = append(allErrs, field.Invalid(fldPath, "", err.Error()))
} else {
err = s.Ping()
output, err := s.CombinedOutput("whoami")
if err != nil {
allErrs = append(allErrs, field.Invalid(fldPath, "", err.Error()))
}
if strings.TrimSpace(string(output)) != "root" {
allErrs = append(allErrs, field.Invalid(fldPath.Child("user"), user, `must be root or set sudo without password`))
}
}

return allErrs
Expand Down
2 changes: 1 addition & 1 deletion pkg/platform/provider/baremetal/cluster/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ func (p *Provider) EnsureDisableSwap(ctx context.Context, c *v1.Cluster) error {
return err
}

_, err = machineSSH.CombinedOutput("swapoff -a && sed -i 's/^[^#]*swap/#&/' /etc/fstab")
_, err = machineSSH.CombinedOutput(`swapoff -a && sed -i "s/^[^#]*swap/#&/" /etc/fstab`)
if err != nil {
return errors.Wrap(err, machine.IP)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/platform/provider/baremetal/machine/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ func (p *Provider) EnsureDisableSwap(ctx context.Context, machine *platformv1.Ma
return err
}

_, err = machineSSH.CombinedOutput("swapoff -a && sed -i 's/^[^#]*swap/#&/' /etc/fstab")
_, err = machineSSH.CombinedOutput(`swapoff -a && sed -i "s/^[^#]*swap/#&/" /etc/fstab`)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/platform/provider/baremetal/phases/kubelet/kubelet.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func Install(s ssh.Interface, version string) (err error) {

for _, file := range []string{"kubelet", "kubectl"} {
file = path.Join(constants.DstBinDir, file)
if _, err := s.Stat(file); err == nil {
if ok, err := s.Exist(file); err == nil && ok {
backupFile, err := ssh.BackupFile(s, file)
if err != nil {
return fmt.Errorf("backup file %q error: %w", file, err)
Expand Down
6 changes: 2 additions & 4 deletions pkg/platform/provider/baremetal/preflight/checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,7 @@ func (fac FileAvailableCheck) Name() string {

// Check validates if the given file does not already exist.
func (fac FileAvailableCheck) Check() (warnings, errorList []error) {

if _, err := fac.Stat(fac.Path); err == nil {
if ok, err := fac.Exist(fac.Path); err == nil && ok {
errorList = append(errorList, errors.Errorf("%s already exists", fac.Path))
}
return nil, errorList
Expand Down Expand Up @@ -365,8 +364,7 @@ func (dac DirAvailableCheck) Name() string {

// Check validates if a directory does not exist or empty.
func (dac DirAvailableCheck) Check() (warnings, errorList []error) {

if _, err := dac.Stat(dac.Path); err == nil {
if ok, err := dac.Exist(dac.Path); err == nil && ok {
errorList = append(errorList, errors.Errorf("%s already exists", dac.Path))
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/util/cmdstring/cmdstring.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import "fmt"

// SetFileContent generates cmd for set file content.
func SetFileContent(file, pattern, content string) string {
return fmt.Sprintf("grep -Pq '%s' %s && sed -i 's;%s;%s;g' %s|| echo '%s' >> %s",
return fmt.Sprintf(`grep -Pq "%s" %s && sed -i "s;%s;%s;g" %s|| echo "%s" >> %s`,
pattern, file,
pattern, content, file,
content, file)
Expand Down
72 changes: 72 additions & 0 deletions pkg/util/ssh/helper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Tencent is pleased to support the open source community by making TKEStack
* available.
*
* Copyright (C) 2012-2020 Tencent. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the “License”); you may not use
* this file except in compliance with the License. You may obtain a copy of the
* License at
*
* https://opensource.org/licenses/Apache-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS, WITHOUT
* WARRANTIES OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package ssh

import (
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"io/ioutil"

"golang.org/x/crypto/ssh"
)

func MakePrivateKeySignerFromFile(key string) (ssh.Signer, error) {
// Create an actual signer.
buffer, err := ioutil.ReadFile(key)
if err != nil {
return nil, fmt.Errorf("error reading SSH key %s: '%v'", key, err)
}
return MakePrivateKeySigner(buffer, nil)
}

func MakePrivateKeySigner(privateKey []byte, passPhrase []byte) (ssh.Signer, error) {
var signer ssh.Signer
var err error
if passPhrase == nil {
signer, err = ssh.ParsePrivateKey(privateKey)
} else {
signer, err = ssh.ParsePrivateKeyWithPassphrase(privateKey, passPhrase)
}
if err != nil {
return nil, fmt.Errorf("error parsing SSH key: '%v'", err)
}
return signer, nil
}

func ParsePublicKeyFromFile(keyFile string) (*rsa.PublicKey, error) {
buffer, err := ioutil.ReadFile(keyFile)
if err != nil {
return nil, fmt.Errorf("error reading SSH key %s: '%v'", keyFile, err)
}
keyBlock, _ := pem.Decode(buffer)
if keyBlock == nil {
return nil, fmt.Errorf("error parsing SSH key %s: 'invalid PEM format'", keyFile)
}
key, err := x509.ParsePKIXPublicKey(keyBlock.Bytes)
if err != nil {
return nil, fmt.Errorf("error parsing SSH key %s: '%v'", keyFile, err)
}
rsaKey, ok := key.(*rsa.PublicKey)
if !ok {
return nil, fmt.Errorf("SSH key could not be parsed as rsa public key")
}
return rsaKey, nil
}
36 changes: 36 additions & 0 deletions pkg/util/ssh/interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Tencent is pleased to support the open source community by making TKEStack
* available.
*
* Copyright (C) 2012-2020 Tencent. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the “License”); you may not use
* this file except in compliance with the License. You may obtain a copy of the
* License at
*
* https://opensource.org/licenses/Apache-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS, WITHOUT
* WARRANTIES OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package ssh

import "io"

type Interface interface {
Ping() error

CombinedOutput(cmd string) ([]byte, error)
Execf(format string, a ...interface{}) (stdout string, stderr string, exit int, err error)
Exec(cmd string) (stdout string, stderr string, exit int, err error)

CopyFile(src, dst string) error
WriteFile(src io.Reader, dst string) error
ReadFile(filename string) ([]byte, error)
Exist(filename string) (bool, error)

LookPath(file string) (string, error)
}
File renamed without changes.
Loading

0 comments on commit 48cbf22

Please sign in to comment.