Skip to content

Commit

Permalink
Set emergency login for core user with random password
Browse files Browse the repository at this point in the history
This PR allow user to set the emergency login for core user with a
random generated password. It is helpful when user lost the ssh access
and use VMM to debug the issue which require password for `core` user.

Generated password is stored in `~/.crc/machine/crc/passwd` file which
user can consume in case of debugging. When user unset the
`enable-emergency-login` setting then password is locked for `core`
user.

```
$ crc config set enable-emergency-login true
$ crc config view
- enable-emergency-login                : true
[...]
$ crc start
[...]
INFO CRC VM is running
INFO Emergency login password for core user is stored to /home/prkumar/.crc/machines/crc/passwd
INFO Updating authorized keys...
[...]
```
  • Loading branch information
gbraad authored and praveenkumar committed Aug 7, 2023
1 parent 5d48458 commit f4b61ec
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 0 deletions.
2 changes: 2 additions & 0 deletions cmd/crc/cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ func runStart(ctx context.Context) (*types.StartResult, error) {
IngressHTTPPort: config.Get(crcConfig.IngressHTTPPort).AsUInt(),
IngressHTTPSPort: config.Get(crcConfig.IngressHTTPSPort).AsUInt(),
EnableSharedDirs: config.Get(crcConfig.EnableSharedDirs).AsBool(),

EmergencyLogin: config.Get(crcConfig.EmergencyLogin).AsBool(),
}

client := newMachine()
Expand Down
1 change: 1 addition & 0 deletions pkg/crc/api/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ func getStartConfig(cfg crcConfig.Storage, args client.StartConfig) types.StartC
IngressHTTPSPort: cfg.Get(crcConfig.IngressHTTPSPort).AsUInt(),
Preset: crcConfig.GetPreset(cfg),
EnableSharedDirs: cfg.Get(crcConfig.EnableSharedDirs).AsBool(),
EmergencyLogin: cfg.Get(crcConfig.EmergencyLogin).AsBool(),
}
}

Expand Down
3 changes: 3 additions & 0 deletions pkg/crc/config/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const (
SharedDirPassword = "shared-dir-password" // #nosec G101
IngressHTTPPort = "ingress-http-port"
IngressHTTPSPort = "ingress-https-port"
EmergencyLogin = "enable-emergency-login"
)

func RegisterSettings(cfg *Config) {
Expand Down Expand Up @@ -88,6 +89,8 @@ func RegisterSettings(cfg *Config) {
"Disable update check (true/false, default: false)")
cfg.AddSetting(ExperimentalFeatures, false, ValidateBool, SuccessfullyApplied,
"Enable experimental features (true/false, default: false)")
cfg.AddSetting(EmergencyLogin, false, ValidateBool, SuccessfullyApplied,
"Enable emergency login for 'core' user. Password is randomly generated. (true/false, default: false)")

// Shared directories configs
if runtime.GOOS == "windows" {
Expand Down
1 change: 1 addition & 0 deletions pkg/crc/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ var (
MachineInstanceDir = filepath.Join(MachineBaseDir, "machines")
DaemonSocketPath = filepath.Join(CrcBaseDir, "crc.sock")
KubeconfigFilePath = filepath.Join(MachineInstanceDir, DefaultName, "kubeconfig")
PasswdFilePath = filepath.Join(MachineInstanceDir, DefaultName, "passwd")
)

func GetDefaultBundlePath(preset crcpreset.Preset) string {
Expand Down
35 changes: 35 additions & 0 deletions pkg/crc/machine/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"crypto/x509"
"encoding/json"
"fmt"
"math/rand"
"os"
"path/filepath"
"strconv"
Expand All @@ -32,6 +33,7 @@ import (
"github.com/crc-org/crc/pkg/crc/telemetry"
crctls "github.com/crc-org/crc/pkg/crc/tls"
"github.com/crc-org/crc/pkg/libmachine/host"
crcos "github.com/crc-org/crc/pkg/os"
"github.com/crc-org/machine/libmachine/drivers"
libmachinestate "github.com/crc-org/machine/libmachine/state"
"github.com/docker/go-units"
Expand Down Expand Up @@ -417,6 +419,16 @@ func (client *client) Start(ctx context.Context, startConfig types.StartConfig)
}
logging.Info("CRC VM is running")

if startConfig.EmergencyLogin {
if err := enableEmergencyLogin(sshRunner); err != nil {
return nil, errors.Wrap(err, "Error enabling emergency login")
}
} else {
if err := disableEmergencyLogin(sshRunner); err != nil {
return nil, errors.Wrap(err, "Error deleting the password for core user")
}
}

// Post VM start immediately update SSH key and copy kubeconfig to instance
// dir and VM
if err := updateSSHKeyPair(sshRunner); err != nil {
Expand Down Expand Up @@ -784,6 +796,29 @@ func addNameServerToInstance(sshRunner *crcssh.Runner, ns string) error {
return nil
}

func enableEmergencyLogin(sshRunner *crcssh.Runner) error {
if crcos.FileExists(constants.PasswdFilePath) {
return nil
}
charset := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
b := make([]byte, 8)
for i := range b {
b[i] = charset[rand.Intn(len(charset))] //nolint
}
if err := os.WriteFile(constants.PasswdFilePath, b, 0600); err != nil {
return err
}
logging.Infof("Emergency login password for core user is stored to %s", constants.PasswdFilePath)
_, _, err := sshRunner.Run(fmt.Sprintf("sudo passwd core --unlock && echo %s | sudo passwd core --stdin", b))
return err
}

func disableEmergencyLogin(sshRunner *crcssh.Runner) error {
defer os.Remove(constants.PasswdFilePath)
_, _, err := sshRunner.RunPrivileged("disable core user password", "passwd", "--lock", "core")
return err
}

func updateSSHKeyPair(sshRunner *crcssh.Runner) error {
// Read generated public key
publicKey, err := os.ReadFile(constants.GetPublicKeyPath())
Expand Down
3 changes: 3 additions & 0 deletions pkg/crc/machine/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ type StartConfig struct {
// Ports to access openshift routes
IngressHTTPPort uint
IngressHTTPSPort uint

// Enable emergency login
EmergencyLogin bool
}

type ClusterConfig struct {
Expand Down

0 comments on commit f4b61ec

Please sign in to comment.