in lib/ec2macosinit/systemconfig.go [336:478]
func (c *SystemConfigModule) configureSSHD(ctx *ModuleContext) (configChanges bool, err error) {
// Look for each thing and fix them if found
sshdFile, err := os.Open(sshdConfigFile)
if err != nil {
log.Fatal(err)
}
defer sshdFile.Close()
// Create scanner for the SSHD file
scanner := bufio.NewScanner(sshdFile)
// Create a new temporary file, if changes are detected, it will be moved over the existing file
tempSSHDFile, err := os.CreateTemp("", "sshd_config_fixed.*")
if err != nil {
return false, fmt.Errorf("ec2macosinit: error creating %s", tempSSHDFile.Name())
}
defer tempSSHDFile.Close()
// Keep track of line number simply for confirming warning header
var lineNumber int
// Track the last line for adding in warning when needed
var lastLine string
// Iterate over every line in the file
for scanner.Scan() {
lineNumber++
currentLine := scanner.Text()
// If this is the first line in the file, look for the warning header and add if missing
if lineNumber == 1 && currentLine != ConfigurationManagementWarning {
_, err = tempSSHDFile.WriteString(ConfigurationManagementWarning + "\n")
if err != nil {
return false, fmt.Errorf("ec2macosinit: error writing to %s", tempSSHDFile.Name())
}
configChanges = true
lastLine = ConfigurationManagementWarning
}
switch {
// Check if PasswordAuthentication is enabled, if so put in warning and change the config
// PasswordAuthentication allows SSHD to respond to user password brute force attacks and can result in lowered
// security, especially if a simple password is set. In EC2, this is undesired and therefore turned off by default
case strings.Contains(currentLine, "PasswordAuthentication yes"):
err = checkAndWriteWarning(lastLine, tempSSHDFile)
if err != nil {
return false, fmt.Errorf("ec2macosinit: error writing to %s", tempSSHDFile.Name())
}
// Overwrite with desired configuration line
_, err = tempSSHDFile.WriteString("PasswordAuthentication no\n")
if err != nil {
return false, fmt.Errorf("ec2macosinit: error writing to %s", tempSSHDFile.Name())
}
// Changes detected so this will enforce updating the file later
configChanges = true
// Check if PAM is enabled, if so, put in warning and change the config
// PAM authentication enables challenge-response authentication which can allow brute force attacks on SSHD
// In EC2, this is undesired and therefore turned off by default
case strings.TrimSpace(currentLine) == "UsePAM yes":
err = checkAndWriteWarning(lastLine, tempSSHDFile)
if err != nil {
return false, fmt.Errorf("ec2macosinit: error writing to %s", tempSSHDFile.Name())
}
// Overwrite with desired configuration line
_, err = tempSSHDFile.WriteString("UsePAM no\n")
if err != nil {
return false, fmt.Errorf("ec2macosinit: error writing to %s", tempSSHDFile.Name())
}
// Changes detected so this will enforce updating the file later
configChanges = true
// Check if Challenge-response is enabled, if so put in warning and change the config
// Challenge-response authentication via SSHD can allow brute force attacks for SSHD. In EC2, this is undesired
// and therefore turned off by default
case strings.Contains(currentLine, "ChallengeResponseAuthentication yes"):
err = checkAndWriteWarning(lastLine, tempSSHDFile)
if err != nil {
return false, fmt.Errorf("ec2macosinit: error writing to %s", tempSSHDFile.Name())
}
// Overwrite with desired configuration line
_, err = tempSSHDFile.WriteString("ChallengeResponseAuthentication no\n")
if err != nil {
return false, fmt.Errorf("ec2macosinit: error writing to %s", tempSSHDFile.Name())
}
// Changes detected so this will enforce updating the file later
configChanges = true
default:
// Otherwise write the line as is to the temp file without modification
_, err = tempSSHDFile.WriteString(currentLine + "\n")
if err != nil {
return false, fmt.Errorf("ec2macosinit: error writing to %s", tempSSHDFile.Name())
}
}
// Rotate the current line to the last line so that comments can be inserted above rewritten lines
lastLine = currentLine
}
if err := scanner.Err(); err != nil {
return false, fmt.Errorf("ec2macosinit: error reading %s: %s", sshdConfigFile, err)
}
// If there was a change detected, then copy the file and restart sshd
if configChanges {
// Get the current status of SSHD, if its not running, then it should not be started
sshdRunning, err := c.checkSSHDReturn()
if err != nil {
ctx.Logger.Errorf("ec2macosinit: unable to get SSHD status: %s", err)
}
// Move the temporary file to the SSHDConfigFile
err = os.Rename(tempSSHDFile.Name(), sshdConfigFile)
if err != nil {
return false, fmt.Errorf("ec2macosinit: unable to save updated configuration to %s", sshdConfigFile)
}
// Temporary files have different permissions by design, correct the permissions for SSHDConfigFile
err = os.Chmod(sshdConfigFile, 0644)
if err != nil {
return false, fmt.Errorf("ec2macosinit: unable to set correct permssions of %s", sshdConfigFile)
}
// If SSHD was detected as running, then a restart must happen, if it was not running, the work is complete
if sshdRunning {
// Unload and load SSHD, the launchctl method for re-loading SSHD with new configuration
_, err = executeCommand([]string{"/bin/zsh", "-c", "launchctl unload /System/Library/LaunchDaemons/ssh.plist"}, "", []string{})
if err != nil {
ctx.Logger.Errorf("ec2macosinit: unable to stop SSHD %s", err)
return false, fmt.Errorf("ec2macosinit: unable to stop SSHD %s", err)
}
_, err = executeCommand([]string{"/bin/zsh", "-c", "launchctl load -w /System/Library/LaunchDaemons/ssh.plist"}, "", []string{})
if err != nil {
ctx.Logger.Errorf("ec2macosinit: unable to restart SSHD %s", err)
return false, fmt.Errorf("ec2macosinit: unable to restart SSHD %s", err)
}
// Add the message to state that config was modified and SSHD was correctly restarted
ctx.Logger.Info("Modified SSHD configuration and restarted SSHD for new configuration")
} else {
// Since SSHD was not running, only change the configuration but no restarting is desired
ctx.Logger.Info("Modified SSHD configuration, did not restart SSHD since it was not running")
}
} else {
// There were no changes detected from desired state, simply exit and let the temp file be
ctx.Logger.Info("Did not modify SSHD configuration")
}
// Return the message to caller for logging
return configChanges, nil
}