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.

1
  • 1
    Did you ever find a solution for this?
    – span
    Feb 6, 2015 at 15:26

4 Answers 4

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.

0
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.

3
  • Note that these timeouts won't work everywhere: reprepro can easily take over 5 seconds before prompting for some passphrase. Setting timeout to 30 fixed my last issue, TY!
    – SYN
    May 20, 2017 at 13:42
  • Although I like this solution, I'm struggeling with passing the arguments to reprepro. Calling this script with "reprepro.ext -b /path/to/repo include ..." fails, with /usr/bin/expect: option requires an argument -- 'b'. Obviously expect interprets the parameters for it's own, rather than passing it to reprepro? Any hints?
    – joergd
    Feb 25, 2020 at 10:44
  • Found a solution: To prevent "expect" to parse your passed arguments, invoke it with reprepro.exp -- -b /path/to/repo ....
    – joergd
    Feb 25, 2020 at 10:54
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!

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .