4

I use "reprepro" for getting the latest Debian packages out of my local repository, which works fine manually.
Now I need to automate this process through a cron job but the reprepro passphrase is a prompt.

Is there any possibility to send the password via bash script? Couldn't find anything in the reprepro manpage.

αғsнιη
  • 36,350
P4tR
  • 55

4 Answers4

6

I needed the same thing and was looking for solution. Apart from running gpg-agent, which will ask for the password only once (e.g. during boot) and cache it for next usage, I have found nothing.

Problem is how to interact with interactive scripts, which are the ones, who ask for user input from stdin. Expect (apt-get install expect) solves exactly that.

This is the script I wrote and saved in /usr/local/bin/reprepro_expect:

#!/usr/bin/expect -f
set timeout 2
set passphrase "mysupersecretpassword"

spawn reprepro -b [lindex $argv 0] [lindex $argv 1] [lindex $argv 2] [lindex $argv 3]
expect {
        "*passphrase:*" {
                send -- "$passphrase\r"
        }
}
expect {
        "*passphrase:*" {
                send -- "$passphrase\r"
        }
}
interact

You can run it like this:

reprepro_expect [path_to_repository] [command] [distribution] [package_name]

For example:

Add new package:

reprepro_expect /var/www/myrepo includedeb wheezy mypackage_0.1-1_all.deb

Delete package

reprepro_expect /var/www/myrepo remove wheezy mypackage

Security: Since password to your private key is stored in the script, I recommend to chown it to user, under which it will be used and chmod it to 500. Why isn't passphrase passed as another argument? Because it would be stored in ~/.bash_history and it would show in ps axu during runtime.

mkudlacek
  • 176
2

As mentioned in other answers, expect can solve this problem. I ended up with something like this, save as reprepro.exp and make it executable with chmod 755 reprepro.exp

#!/usr/bin/expect -f

set timeout 5

set passphrase "$env(SIGNING_PASSWORD)"

# Call reprepro with variable length arguments, so that this script
# takes the same arguments as the original program
spawn reprepro {*}$argv

expect {
    timeout                     {send_error "\nFailed to get password prompt\n";
                                 exit 1}
    "Please enter passphrase*"  {send -- "$passphrase\r";
                                 send_user " *** entering passphrase ***";
                                 exp_continue}
}

# Get the pid, spawnid, oserr and exitcode from the spawned reprepro command
set returnvalues [wait]

# Extract the reprepro exit code
set exitcode [lindex $returnvalues 3]

# Exit with the exitcode from reprepro (0 on success)
exit $exitcode

Having one expect statement means that this will also work (i.e. not crash) if the password is wrong. Then gpg will ask for the passphrase three times and reprepro will return an exit code that is not 0.

You can export the environment variable SIGNING_PASSWORD in your .bashrc or replace it in the script with the real password or do something else. Use the appropriate level of security that you need.

1

My working code. I echo the scipt inside an other bashscript into a file and open it then.

#!/usr/bin/expect -f
set timeout 5
spawn reprepro -v -b $SCRIPT_DIR/repository/ubuntu includedeb $UBUNTUVERSION $DEBFILE
expect {
    timeout                     {send_error \"\\nFailed to get password prompt\\n\";
                                 exit 1}
    \"Pass*\"  {send -- \"$KEYPASSWD\\r\";
                                 send_user \" *** entering passphrase ***\";
                                 exp_continue}
}
# Get the pid, spawnid, oserr and exitcode from the spawned reprepro command
set returnvalues [wait]

Extract the reprepro exit code

set exitcode [lindex $returnvalues 3]

Exit with the exitcode from reprepro (0 on success)

exit $exitcode

Don't forget to run the command update-alternatives --set pinentry /usr/bin/pinentry-tty >/dev/null || gpg-connect-agent reloadagent /bye >/dev/null, so reprepro does not want to open a graphical user input!

pfennig
  • 11
0

This Answer is for ansible users.
I had the same problem, I created a dummy file, encrypted it, and used the gpg-agent to cache the password like suggested by mkudlacek, but with the ansible expect module. I used the following tasks:

- name: create test.txt, created a dummy file
  file:
    path: /test.txt
    state: touch
    mode: u=rw,g=rw,o=rw #!!! just for testing purposes
  • name: encrypt file expect: command: gpg --pinentry-mode loopback --sign /test.txt responses: 'Enter passphrase:': '{{ your_pw }}' timeout: 60

You can add now the Reprepro Packages via a separate Task and delete the test.txt file.