Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use alternative privilege escalation command to initialize the environment #799

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 57 additions & 3 deletions pkg/cluster/task/env_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ import (
"github.com/pingcap/tiup/pkg/cluster/module"
)

// PrivilegeEscalationMethod defiles availabile linux privilege escalation commands
type PrivilegeEscalationMethod int

const (
// Invalid privilege escalation mathod as a default
Invalid PrivilegeEscalationMethod = 0
// Sudo command
Sudo PrivilegeEscalationMethod = 1
//Su command
Su PrivilegeEscalationMethod = 2
//Runuser command
Runuser PrivilegeEscalationMethod = 3
)

var (
errNSEnvInit = errNS.NewSubNamespace("env_init")
errEnvInitSubCommandFailed = errNSEnvInit.NewType("sub_command_failed")
Expand Down Expand Up @@ -74,18 +88,58 @@ func (e *EnvInit) execute(ctx *Context) error {
return wrapError(err)
}

// some of the privilege escalation commands might be prohibited by the linux administrator
// try different methods and choose the one that works (su, runuser, sudo)
// raise an error when there is no privilege escalation method available
var privilegeEscalationMethod PrivilegeEscalationMethod = Invalid
pems := map[PrivilegeEscalationMethod]string{
Su: fmt.Sprintf(`su - %s -c 'echo 0'`, e.deployUser),
Runuser: fmt.Sprintf(`runuser -l %s -c 'echo 0'`, e.deployUser),
Sudo: `sudo echo 0`,
}
for pem, cmd := range pems {
_, _, err = exec.Execute(cmd, true)
if err == nil {
privilegeEscalationMethod = pem
break
}
}
if privilegeEscalationMethod == Invalid {
return wrapError(errEnvInitSubCommandFailed.
Wrap(err, "No privilege escalation method available"))
}

// Authorize
cmd := `su - ` + e.deployUser + ` -c 'mkdir -p ~/.ssh && chmod 700 ~/.ssh'`
var cmd string
switch privilegeEscalationMethod {
case Su:
cmd = fmt.Sprintf(`su - %s -c 'test -d ~/.ssh || mkdir -p ~/.ssh && chmod 700 ~/.ssh'`, e.deployUser)
case Runuser:
cmd = fmt.Sprintf(`runuser -l %s -c 'test -d ~/.ssh || mkdir -p ~/.ssh && chmod 700 ~/.ssh'`, e.deployUser)
case Sudo:
cmd = fmt.Sprintf(`sudo test -d ~/.ssh || sudo mkdir -p ~/.ssh && sudo chmod 700 ~/.ssh && sudo chown %s:%s ~/.ssh`, e.deployUser, e.userGroup)
}
_, _, err = exec.Execute(cmd, true)
if err != nil {
return wrapError(errEnvInitSubCommandFailed.
Wrap(err, "Failed to create '~/.ssh' directory for user '%s'", e.deployUser))
}

pk := strings.TrimSpace(string(pubKey))

sshAuthorizedKeys := executor.FindSSHAuthorizedKeysFile(exec)
cmd = fmt.Sprintf(`su - %[1]s -c 'grep $(echo %[2]s) %[3]s || echo %[2]s >> %[3]s && chmod 600 %[3]s'`,
e.deployUser, pk, sshAuthorizedKeys)
switch privilegeEscalationMethod {
case Su:
cmd = fmt.Sprintf(`su - %[1]s -c 'grep $(echo %[2]s) %[3]s || echo %[2]s >> %[3]s && chmod 600 %[3]s'`,
e.deployUser, pk, sshAuthorizedKeys)
case Runuser:
cmd = fmt.Sprintf(`runuser -l %[1]s -c 'grep $(echo %[2]s) %[3]s || echo %[2]s >> %[3]s && chmod 600 %[3]s'`,
e.deployUser, pk, sshAuthorizedKeys)
case Sudo:
cmd = fmt.Sprintf(`sudo grep $(echo %[1]s) %[2]s || sudo echo %[1]s >> %[2]s && chmod 600 %[2]s && sudo chown %[3]s:%[4]s %[2]s`,
pk, sshAuthorizedKeys, e.deployUser, e.userGroup)
}

_, _, err = exec.Execute(cmd, true)
if err != nil {
return wrapError(errEnvInitSubCommandFailed.
Expand Down