4

I have a configuration file located at /etc/ssh/sshd_config that may or may not include a configuration line that sets PermitRootLogin.

PermitRootLogin yes

My goal is to either change this value to something I know is correct (regardless of the current value), or to add the configuration line to the end of the file if the configuration value is not currently set in the file.

In other words, I would like a command line one-liner (or as few lines as possible) to do the following:

If a line that begins with PermitRootLogin followed by a space or tab exists, replace the entire line with PermitRootLogin no. Otherwise, add the line PermitRootLogin no to the end of the file.

I want to this to work on the command line (Bash on Linux) so sed, awk, and grep can be used.

I know I can do half of my requirement (if it exists, replace it) with

sed -i 's/^PermitRootLogin[ \t].*$/PermitRootLogin no/' /etc/ssh/sshd_config

If this could be modified to add the line if there was no match, that would work for me.

sed,awk.grep - add a line to the end of a configuration section if the line doesn't already exist is close as well but does not fulfill my full requirement.


Edit: Maintaining the position of a set configuration variable in the file is important to me. The variables are defined in a certain logical order that is useful to human editors. Since this file may be edited by hand in the future, I want to maintain the order. A solution that simply deletes the configuration variable and adds it to the end does not fit my requirements. Thanks.

Community
  • 1
  • 1

3 Answers3

2

This could be done with sed as well:

Usually, these conf files do not have any hard-requirement about the sequence of options. At least sshd_config doesn't have such requirement.

Thus, this sed should work just fine:

sed '/PermitRootLogin/d; ${p;s/.*/PermitRootLogin yes/}' /etc/ssh/sshd_config

If you want to retain the line position in the file, use below command.

sed '1{p;s/.*/PermitRootLogin yes/;h;d;};/^PermitRootLogin/{g;p;s/.*//;h;d;};$G' /etc/ssh/sshd_config

After you've satisfied with the output, add the -i flag to sed command to perform in-place replacement.

anishsane
  • 20,270
  • 5
  • 40
  • 73
1

You can replace sed bu this awk:

awk '/^PermitRootLogin/ {
   found=1;
   sub(/^PermitRootLogin[[:blank:]]+.*$/, "PermitRootLogin no")
}
1; 
END {
   if (!found)
      print "PermitRootLogin no"
}' file
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • For some reason it only replaces when I take `[[:blank:]]` from your code and replace with `[ \t]`. Do you have any idea why that might be? I'm using Debian 8 Jessie so I imagine awk is up to date. –  Apr 24 '15 at 05:11
  • `[[:blank:]]` usually means `[ \t]`. You can use `[ \t]` if that works better for you in your awk – anubhava Apr 24 '15 at 05:19
  • 1
    Yes, I found that in the docs. I'm not sure why it's not working but it certainly should. Anyway, thanks for the superb answer :) –  Apr 24 '15 at 05:25
0

You can add or override default ssh configuration in /etc/ssh/sshd_config.d/ without messing with default sshd_config

# Override sshd configuration
cat << EOF | sudo tee /etc/ssh/sshd_config.d/override.conf
PermitRootLogin no
PasswordAuthentication no
ChallengeResponseAuthentication no
EOF

# Restart sshd service
sudo systemctl restart sshd
Chau Chee Yang
  • 18,422
  • 16
  • 68
  • 132