How to do user interaction on commands in Chef? - ruby

I have some commands which need user interaction so that time either I want to Enter with defaults or feed some input from chef itself so my instance won't fail at run time. For example...
./build-ca # The command I am executing
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [IN]:
State or Province Name (full name) [KA]:
Here pressing enter will does the job (uses defaults) while doint it manually, but how I can automate this thing using Chef, some times I need to press y or other values as well. Any help will be highly appreciated.

If you have no alternatives (e.g. passing arguments or an input file to the command or script, as already suggested by others) you can script the interactions with expect and run it from your chef recipe using the bash resource.
See How to automate user interactive command in chef recipe

I think you are using the Easy RSA scripts to generate OpenVPN certificates.
One solution would be to generate the ./vars file and call pkitool (which is called by the old build-ca script):
easy_rsa_path = '/usr/share/easy-rsa' # or whatever
template "#{easy_rsa_path}/vars" # [...]
bash 'build-ca' do
cwd easy_rsa_path
code <<-EOH
source ./vars && \
./clean-all && \
./pkitool --batch --initca
EOH
creates "#{easy_rsa_path}/keys/ca.crt"
end
A better approach would be to use OpenSSL to generate the certificate. You can see an implementation example in the openvpn cookbook:
bash 'openvpn-initca' do
environment('KEY_CN' => "#{node['openvpn']['key']['org']} CA")
code <<-EOF
openssl req -batch -days #{node["openvpn"]["key"]["ca_expire"]} \
-nodes -new -newkey rsa:#{key_size} -sha1 -x509 \
-keyout #{node["openvpn"]["signing_ca_key"]} \
-out #{node["openvpn"]["signing_ca_cert"]} \
-config #{key_dir}/openssl.cnf
EOF
not_if { ::File.exists?(node['openvpn']['signing_ca_cert']) }
end

Related

openssl command fail on one windows machine in GitBash window while works on another

This command fails on one Windows machine in git bash session, while on the other machine it work fine.
auser#pc MINGW64 /c/Developer/TEMP/openssltest
$ echo "Hi Alice!" | openssl rsautl -encrypt -inkey /c/Developer/TEMP/openssltest/pub2.pem --pubin
Can't open /c/Developer/TEMP/openssltest/pub2.pem for reading, No such file or directory
15844:error:02001003:system library:fopen:No such process:../openssl-1.1.1k/crypto/bio/bss_file.c:69:fopen('/c/Developer/TEMP/openssltest/pub2.pem','r')
15844:error:2006D080:BIO routines:BIO_new_file:no such file:../openssl-1.1.1k/crypto/bio/bss_file.c:76:
unable to load Public Key
auser#pc
This command work on a machine where it fails
$ echo "Hi Alice!" | openssl rsautl -encrypt -inkey ./pub2.pem --pubin
I do not have any issues on another machine. Where to look?
I would look into:
difference in openssl version
read access: cat /c/Developer/TEMP/openssltest/pub2.pem (or cat /c/Developer/TEMP/anyOtherFile)
difference in user for the shell session (env|grep -i user)
If you are running that test with a user account which does not have the right to read that TEMP folder, you would get that error.

How to use encrypted and decrypted passwords in shell script

I am writing a shell script which executes a command which requires a password. I cannot put password in plain text in the script. I read about openssl encrypt decrypt mechanism but for encrypting a file again I need a password which again I cannot put in the script. I am clueless what is the best way to have a script execute a command using a secure password.
After reading about Using OpenSSL to encrypt messages and files on Linux, the following approach might work for you.
Assuming you have private and public key generated for your machine
openssl genrsa -out passwordPrivKey.pem 2048
openssl rsa -in passwordPrivKey.pem -out passwordPubKey.pem -outform PEM -pubout
OpenSSL could be used than to encrypt and decrypt a password. Providing a script stub which will demonstrate how to use the command.
#!/bin/bash
echo -n "password" > PASSWORD.plain
# To encrypt
openssl rsautl -encrypt -inkey ./passwordPrivKey.pem -pubin -in PASSWORD.plain -out PASSWORD.dat
# To decrypt
DECRYPTED=$(openssl rsautl -decrypt -inkey ./passwordPubKey.pem -in PASSWORD.dat)
echo $DECRYPTED
On the machine where the password is needed unencrypted later, only PASSWORD.dat and passwordPubKey.pem would be stored.
You may also interested in Hiding Password in Shell Scripts, Password encryption and decryption or How does OpenSSL decrypt a password.
Try openssl. It is a command available on UNIX and it can hash your password for you.
https://www.openssl.org/docs/man1.0.2/apps/openssl.html
It depends on where you execute that script from. If it's a continuous integration tool, there should be way to define a system variable, visible in your script.

Simple way to encrypt and decrypt a backup file in bash

I need to encrypt a backup file gzip.
I performed the following operation.,
tar -Pzcvf $dir/*.xml >/dev/null | gpg --yes --batch --passphrase PaSsW0rD -o "$bpath/$bfile".tar.gz
But it is failing with the following error.,
gpg: processing message failed: Unknown system error
I just need a simple passsord protected backup file. Any other alternative solutions are also welcome.
Thanks in advance
Option 1
Doing it your way :
tar -zcvf your_tar_file_name.tar.gz "$dir"/*.xml && gpg --symmetric --cipher-algo AES256 your_tar_file_name.tar.gz
Note that I do not wish to preserve absolute names, so I have stripped the P option from tar. The default output file in this case is your_tar_file_name.tar.gz.gpg.
To decrypt and get the files back you may do :
gpg -o my_tar_file.tar.gz -d your_tar_file_name.tar.gz.gpg && tar -xzf my_tar_file.tar.gz
This uses a symmetric encryption scheme, ie, we could use the same password to decrypt the file. The above command will ask you to enter the password for encryption and confirm it.
If you wish to do asymmetric encryption using gpg have a look at this tutorial.
Option 2
You may also use aescrypt
Download aescrypt from here
Once installed you may use the straight-forward GUI to encrypt the file.
If you need the command line tool, you could use the aescrypt command like below:
tar zcvf your_tar_file_name.tar.gz "$dir"/*.xml && aescrypt -e -p yourstrongpassword your_tar_file_name.tar.gz
Here e is for encryption and p is for password. The output will usually be stored in your_tar_file_name.tar.gz.aes.
You could decrypt the your_tar_file_name.tar.gz.aes file using
aescrypt -d -p yourstrongpassword your_tar_file_name.tar.gz.aes
Here d is for decryption.

Scripting openssl to generate many certificates without manually entering password?

I have created a certificate authority and need to generate and sign 50+ certificates. I wanted to script this process. I don't want to have to manually enter a password 100+ times!
Here is the command I was getting hung up on:
openssl req -newkey rsa:1024 -keyout ~/myCA/tempkey.pem -keyform PEM -out ~/myCA/tempreq.pem -outform PEM
The problem is, it wants me to create a password with these prompts:
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
When I am just being asked for a password to input I can use the -passin pass:mypass command line option for openssl. But this does not seem to work for creating a password.
Also, it seems strange that a password is required when later I just end up removing it with:
openssl rsa < tempkey.pem > server_key.pem
I tried creating a simple Ruby script:
require 'open3'
Open3.popen2("openssl req -newkey rsa:1024 -keyout ~/myCA/tempkey.pem -keyform PEM -out ~/myCA/tempreq.pem -outform PEM") {|i,o,t|
i.puts "mySecretPassword"
i.puts "mySecretPassword"
}
But this does not seem to work either. I still end up with a manual prompt asking me to create a password.
As explained in this answer you can use the -passout pass:foobar option to set a password via command line. For example:
openssl req \
-newkey rsa:1024 -keyout ~/myCA/tempkey.pem -keyform PEM \
-out ~/myCA/tempreq.pem -outform PEM \
-passout pass:foobar \
-subj "/C=US/ST=Test/L=Test/O=Test/CN=localhost"
The problem is most of utilities that expects a password do require interactive terminal. So if you try to fake it (like you did with a Ruby script) it will not work. You could also try:
echo -n "pass\npass\n" | openssl req ....
While this will work with some programs, those what require interative shell will not work.
You are searching for the tool called expect. Install it on your UNIX/Linux/MacOS and see the man page:
man expect
...
Expect is a program that "talks" to other interactive programs according to a script. Following the script, Expect
knows what can be expected from a program and what the correct response should be. An interpreted language pro‐
vides branching and high-level control structures to direct the dialogue. In addition, the user can take control
and interact directly when desired, afterward returning control to the script.
...
You need to create "expect script", it really depends on your environment - what the application is asking for. If it is only a passwords, it should be simple. Here is more complex example: http://fixunix.com/openssl/159046-expect-script-doesnt-create-newreq-pem.html
I think this should work (you will maybe need to change it a bit):
#!/usr/bin/expect -f
spawn -console openssl req blah blah blah blah
expect "Enter PEM pass phrase:*" {send "password\r"}
expect "Verifying - Enter PEM pass phrase:*" {send "password\r"}
Good luck!

How to generate a CSR without having a key file?

I am trying to run OpenSSL from Node.js in order to create a CSR. Basically, this works fine, but now I have a problem I can not solve.
Basically, what I want to do is to create a CSR from a key. The appropriate command is
$ openssl req -key private.key -new -subj "/C=DE/ST=..."
This outputs the CSR to stdout. So far, this is fine. What I now want to change is that I do not need to have the private key in a special file, instead I want to provide it from stdin. So, basically I'd like to run OpenSSL like this:
$ openssl req -new -subj "/C=DE/ST=..."
But since the -key parameter is now missing, this forces OpenSSL to create a new private key. How can I tell OpenSSL not to create a new private key, but to use the one I provide via stdin?
PS: I am aware of the option to hand over /dev/stdin to the -key parameter, but this will only work on OS X and Linux, not on Windows.

Resources