0

I have a script that should create a file and add content to a file on the hosts listed in a file:

#!/bin/bash

while read f; do

   sshpass -p "mypassword" ssh-copy-id myusername@"$f"
   ssh -ntt myusername@"$f" '
        echo mypassword | sudo -S touch  /etc/sudoers.d/10_icinga_check_postfix_queue || true
        echo mypassword | sudo -S echo "icinga ALL=(ALL) NOPASSWD: /usr/lib64/nagios/plugins/check_postfix_queue" > /etc/sudoers.d/10_icinga_check_postfix_queue || true' </dev/null

done < linux-list.txt

But I get an error and not sure why. can you please help?

bash: line 1: /etc/sudoers.d/10_icinga_check_postfix_queue: Permission denied

Thanks

Irina I
  • 31
  • 1
  • 5
  • 1
    Possible duplicate of [How do I use sudo to redirect output to a location I don't have permission to write to?](https://stackoverflow.com/questions/82256/how-do-i-use-sudo-to-redirect-output-to-a-location-i-dont-have-permission-to-wr) – melpomene Aug 03 '18 at 22:07
  • I tried that solution but no luck - echo my password | sudo -S chmod u+w /etc/sudoers.d/10_icinga_check_postfix_queue – Irina I Aug 03 '18 at 22:23
  • @IrinaI Not that one; the `sudo bash -c ...` solution should work in your case. Note that it's inside a single-quoted string, so you can't use single-quotes (without complications). Also, make sure the file doesn't end up with insecure permissions, or `sudo` will reject it. – Gordon Davisson Aug 04 '18 at 00:20
  • @GordonDavisson thank you but it still doesn't work, maybe I am doing it wrong: sudo bash -c "{ echo 'icinga ALL=(ALL) NOPASSWD: /usr/lib64/nagios/plugins/check_postfix_queue, /usr/lib64/nagios/plugins/contrib/restart_service.sh' > /etc/sudoers.d/10_icinga_check_postfix_queue }" – Irina I Aug 04 '18 at 00:56
  • You're probably running into trouble because of the single-quotes in that. Try replacing them with escaped double-quotes (`\"`). – Gordon Davisson Aug 04 '18 at 01:01
  • @GordonDavisson Still fails... Can you please type the command you have in mind? I tried every combination I knew of ... sudo bash -c "{ echo 'icinga ALL=(ALL) NOPASSWD: /usr/lib64/nagios/plugins/check_postfix_queue, /usr/lib64/nagios/plugins/contrib/restart_service.sh' > /etc/sudoers.d/10_icinga_check_postfix_queue }" – Irina I Aug 04 '18 at 01:05

2 Answers2

1

How about this refactoring of Gordon's answer? There's no need to separately touch the file you are about to overwrite anyway.

#!/bin/bash

while read -r f; do
   sshpass -p "mypassword" ssh-copy-id myusername@"$f"
   ssh -ntt myusername@"$f" '
        echo mypassword | sudo -S bash -c "echo \"icinga ALL=(ALL) NOPASSWD: /usr/lib64/nagios/plugins/check_postfix_queue, /usr/lib64/nagios/plugins/contrib/restart_service.sh\" > /etc/sudoers.d/10_icinga_check_postfix_queue" || true' </dev/null    
done < linux-list.txt

Notice also the (re-) introduction of the -r option to read. It's probably not crucial here, but getting used to it can help avoid unpleasant surprises where it does make a difference.

tripleee
  • 175,061
  • 34
  • 275
  • 318
0

Try this:

#!/bin/bash

while read f; do

   sshpass -p "mypassword" ssh-copy-id myusername@"$f"
   ssh -ntt myusername@"$f" '
        echo mypassword | sudo -S touch  /etc/sudoers.d/10_icinga_check_postfix_queue || true
        echo mypassword | sudo -S bash -c "echo \"icinga ALL=(ALL) NOPASSWD: /usr/lib64/nagios/plugins/check_postfix_queue, /usr/lib64/nagios/plugins/contrib/restart_service.sh\" > /etc/sudoers.d/10_icinga_check_postfix_queue" || true' </dev/null

done < linux-list.txt

This will run the entire echo ... >file command in a sudo shell (rather than just running echo with sudo, and the >file part unprivileged). The tricky thing here is the quoting: there's a single-quoted string that's being passed to ssh as an argument (the commands to run on the remote computer); inside that, there's a double-quoted string being passed to bash -c as the command run (as root), and inside that, there's another quoted string. Since quotes don't nest, the innermost quoted string uses escaped double-quotes (\"), which get passed unchanged when the single-quoted string is parsed on the local computer, then when the outer double-quoted string gets parsed by the remote shell the escapes get removed, so by the time the remote root shell sees it, it's a normal double-quoted string. Yes, this is a mess, but it should work (though I haven't tested it).

Gordon Davisson
  • 118,432
  • 16
  • 123
  • 151
  • 1
    The second `sudo` should not need a password if the `sudo` credential caching is set up properly. I don't think I've seen a site paranoid enough to disable it altogether. – tripleee Aug 06 '18 at 04:12
  • @tripleee Good point; also, as you pointed out in your answer, the `touch` is redundant anyway. – Gordon Davisson Aug 06 '18 at 04:55