Georg Heiler
Georg Heiler

Reputation: 17676

Packer can't execute shell provisioner as sudo

I have a shell provisioner in packer connected to a box with user vagrant

{
  "environment_vars": [
    "HOME_DIR=/home/vagrant"
  ],
  "expect_disconnect": true,
  "scripts": [
    "scripts/foo.sh"
  ],
  "type": "shell"
}

where the content of the script is:

whoami
sudo su
whoami

and the output strangely remains:

==> virtualbox-ovf: Provisioning with shell script: scripts/configureProxies.sh
    virtualbox-ovf: vagrant
    virtualbox-ovf: vagrant

why cant I switch to the root user? How can I execute statements as root? Note, I do not want to quote all statements like sudo "statement |foo" but rather globally switch user like demonstrated with sudo su

Upvotes: 14

Views: 29650

Answers (4)

ufukty
ufukty

Reputation: 472

There is another solution with simpler usage of 2 provisioner together.

Packer's shell provisioner can run the bash with sudo privileges. First you need copy your script file from local machine to remote with file provisioner, then run it with shell provisioner.

packer.json

{
    "vars": [...],
    "builders": [
        {
            # ...
            "ssh_username": "<some_user_other_than_root_with_passwordless_sudo>",
        }
    ],
    "provisioners": [
        {
            "type": "file",
            "source": "scripts/foo.sh",
            "destination": "~/shell.tmp.sh"
        },
        {
            "type": "shell",
            "inline": ["sudo bash ~/shell.tmp.sh"]
        }
    ]
}

foo.sh

# ...
whoami
sudo su root
whoami
# ...

output

<some_user_other_than_root_with_passwordless_sudo>
root

After provisioner complete its task, you can delete the file with shell provisioner.

packer.json updated

        {
            "type": "shell",
            "inline": ["sudo bash ~/shell.tmp.sh", "rm ~/shell.tmp.sh"]
        }

Upvotes: 3

Bruno Bronosky
Bruno Bronosky

Reputation: 70339

Assuming that the shell provisioner you are using is a bash script, you can add my technique to your script.

function if_not_root_rerun_as_root(){
    install_self
    if [[ "$(id -u)" -ne 0 ]]; then
        run_as_root_keeping_exports "$0" "$@"
        exit $?
    fi
}

function run_as_root_keeping_exports(){
    eval sudo $(for x in $_EXPORTS; do printf '%s=%q ' "$x" "${!x}"; done;) "$@"
}

export EXPORTS="PACKER_BUILDER_TYPE PACKER_BUILD_NAME"
if_not_root_rerun_as_root "$@"

There is a pretty good explanation of "$@" here on StackOverflow.

Upvotes: 0

Rickard von Essen
Rickard von Essen

Reputation: 4278

You should override the execute_command. Example:

  "provisioners": [
    {
      "execute_command": "echo 'vagrant' | {{.Vars}} sudo -S -E sh -eux '{{.Path}}'",
      "scripts": [
        "scripts/foo.sh"
      ],
      "type": "shell"
    }
  ],

Upvotes: 14

Georg Heiler
Georg Heiler

Reputation: 17676

one possible answer seems to be: https://unix.stackexchange.com/questions/70859/why-doesnt-sudo-su-in-a-shell-script-run-the-rest-of-the-script-as-root

sudo su <<HERE
ls /root
whoami
HERE

maybe there is a better answer?

Upvotes: 1

Related Questions