Skip to content

SSHKit - Non-passwordless sudo command support #176

@thbar

Description

@thbar

Hello! I would like to discuss an enhancement ; this is a bit of a follow-up of:

Situation

If one connects to a remote server, then issues a command that requires sudo, on a system where the user is not a password less sudo user (for improved security), there is no logic in SSHKit (if I understand) to transmit the user password to the command generation.

This can be reproduced when one comments this line before running mix test:

RUN echo "%passwordless-sudoers ALL=(ALL:ALL) NOPASSWD: ALL" >> /etc/sudoers.d/yolo

mix test
❯ mix test
Running ExUnit with seed: 657181, max_cases: 32
#SNIP

  1) test run/2 with group (SSHKitFunctionalTest)
     test/sshkit_functional_test.exs:103
     Assertion with == failed
     code:  assert status == 0
     left:  1
     right: 0
     stacktrace:
       test/sshkit_functional_test.exs:118: (test)

  2) test run/2 with user (SSHKitFunctionalTest)
     test/sshkit_functional_test.exs:86
     ** (ArgumentError) argument error
     code: IO.puts output
     stacktrace:
       (stdlib 6.2.2.1) io.erl:203: :io.put_chars(:standard_io, [[stderr: "sudo: a password is required\n"], 10])
       test/sshkit_functional_test.exs:97: (test)

  3) test run/2 with path, umask, user, group and env (SSHKitFunctionalTest)
     test/sshkit_functional_test.exs:123
     Assertion with == failed
     code:  assert status == 0
     left:  1
     right: 0
     stacktrace:
       test/sshkit_functional_test.exs:141: (test)

Finished in 22.3 seconds (22.3s async, 0.00s sync)
2 doctests, 159 tests, 3 failures

What is happening (IMO)

My understanding is that there is an implicit requirement that the user (as soon as a user is passed to the context) is passwordless-sudoer, and we go "non interactive" here with -n in that case:

"sudo -H -n -u me -- sh -c '/usr/bin/env whoami'"

Proposal

Passing the password via a specific variable, making sure we obfuscate things properly in case of exception, and inject it interactively when requested, would let users like me cover more scenarios.

Prior art: ServerSpec core SpecInfra does this:

https://github.com/mizzy/specinfra/blob/master/lib/specinfra/backend/ssh.rb#L131-L132

(a lot of other automation tools also do something similar).

A solution similar to this could be to:

  • pass a :sudo_password extra config flag
  • run the command, but watch for the prompt for some time on STDIN
  • reply to the prompt (or timeout)

I do not think it is possible to achieve this right now, without forking (but only had a quick first look).

What do you think?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions