How to set Chef Vault variable in recipe - ruby

Below is the command used to create the vault
knife vault create ldapuser user1 -A "admin,chef1.example.com" -J password.json -M client
Below is the command that shows content of the vault
knife vault show ldapuser user1
id: user1
password: secretp#ssword
username: james
Below is my recipe which includes the following at the very top
chef_gem 'chef-vault' do
compile_time true if respond_to?(:compile_time)
action :install
end
require 'chef-vault'
item = ChefVault::Item.load("ldapuser","user1")
execute 'setup ldap' do
command '/opt/ldap/bin/setup --hostname localhost --port 389 --bindDN cn="Directory Manager" --bindPassword item[password] --ldapport 389 --baseDN "dc=example,dc=com" --addBaseEntry --doNotStart --acceptLicense`
end
execute 'run ldap' do
command '/opt/ldap/bin/ldapmodify --hostname localhost --port 389 --bindDN cn="Directory Manager" --bindPassword item[password] --filename /opt/ldap.ldif
end
Unfortunately once setup is complete and i try to log into my ldap server, i get an invalid credentials error message.
I assume it has to do with how the variable for the bindPassword is defined in the execute block. I even tried logging in using item['password'] and that didnt work. However when i hard code the password (instead of using the vault) into my recipe, i am able to login without any issues.
I have searched everywhere and can't seem to find a solution that works. Please help!

String interpolation in Ruby looks like this: "something #{item['key']} else".
Important bits: use double quotes not single, put #{} around the expression, and make sure you correctly format the expression inside the #{}.

In this example I'm populating a auth.properties and a pem file from secrets from the chef-vault.
Full YouTube Demo Here: How to Create and use Chef-Vault
Default.rb recipe
chef_gem 'chef-vault' do
compile_time true if respond_to?(:compile_time)
end
require 'chef-vault'
secrets = ChefVault::Item.load("vault_demo", "dev_secrets" )
directory "/opt/your_project" do
action :create
end
template '/opt/your_project/auth.properties' do
source "auth.properties.erb"
variables({
sql_password: secrets['sql_password'],
application_password: secrets['application_password']
})
action :create
end
template '/opt/your_project/server.pem' do
source "server.pem.erb"
variables({
ssl_cert: Base64.decode64(secrets['ssl_cert'])
})
action :create
end
Here are the templates:
auth.properties.erb
ssl_password:<%= #sql_password %>
application_password:<%= #application_password %>
server.pem.erb
<%= #ssl_cert %>
Note that the pem file is being base64 decoded in the recipe because it has to be encoded to store in the vault

Related

Running parallel_tests for Ruby-Capybara not working

Running a simple login automation test using Capybara. No database is used.
I am trying to use parallel_test gem to invoke multiple test sessions at the same time (chrome browser) using the following command
parallel_rspec -n 2
two browsers are invoked but only the first one is launched with the correct URL and the second one is simply blank. Also, the login and password values are concatenated twice (data collision) in the first browser input fields.
Framework - Non-rails. Ruby with capybara
config/database.yml
test: &TEST
adapter: postgresql
host: localhost
database: test_db<%= ENV['TEST_ENV_NUMBER'] %>
encoding: utf8
username: postgres
password: postgres
spec_file - 1
describe '' do
it '' do
ENV['TEST_ENV_NUMBER'] = ''
end
end
spec_file - 2
describe '' do
it '' do
ENV['TEST_ENV_NUMBER'] = '2'
end
end
both spec files are in the same folder
There is very little guidance for nonrails setup. Any help would be much appreciated.

Not to store FTP password in Vagrantfile (Vagrant push FTP strategy)

I am developing a small site. I use vagrant for development environment and want to use it for deploy to production. Vagrant docs says that there is Vagrant push FTP strategy.
Config:
config.push.define "ftp" do |push|
push.host = "ftp.company.com"
push.username = "username"
push.password = "password"
end
Usage:
vagrant push
It is quite enough for me, but thing that is stopping me is storing ftp host, username and password in Vagrantfile that is going to my Version Control System and it is bad practice.
Can you give any workaround for this case?
Generate hashed password and store it
openssl passwd -1 "Your_password"
I found solution using config file. Inspired with this question, I moved my sensitive data to separate file. I called it ftp.yml and added to .gitignore
ftp.yml
ftp_host: "host"
ftp_user: "username"
ftp_pass: "password"
.gitignore
ftp.yml
Vagrantfile
# loading FTP config
require 'yaml'
settings = YAML.load_file 'ftp.yml'
Vagrant.configure("2") do |config|
# vm config omitted
config.push.define "ftp" do |push|
push.host = settings['ftp_host']
push.username = settings['ftp_user']
push.password = settings['ftp_pass']
end
end
It worked fine for me.
A simple solution is use of environment variable. It has the important benefit to not store password in clear text.
Vagrantfile:
config.push.define "ftp" do |push|
push.host = "ftp.company.com"
push.username = "username"
push.password = ENV["FTP_PASSWORD"]
end
And export password in environment variable before call to vagrant:
export FTP_PASSWORD='super_secret'
vagrant push
Personally, I use 1Password command-line tool to retrieve password from my vault:
export FTP_PASSWORD=$(op get item ftp.company.com | jq '.details.fields[] | \
select(.designation=="password").value' -r)
vagrant push

Vagrant argv input on terminal complains about machine name

I am trying to pass in arguments (via known ruby methods) to my vagrant up command line, but am getting machine not found errors. What is the correct way to do this in Vagrant?
Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
# Parse options
options = {}
options[:keyfile] = ARGV[1] || false # Your Github authentication keyfile
options[:boxtype] = ARGV[2] || 'virtualbox' # Type of virtual appliance to load
options[:version] = ARGV[3] || 'latest' # Box version to load (not used currently)
ARGV.delete_at(1)
ARGV.delete_at(1)
ARGV.delete_at(1)
Vagrant.configure("2") do | config |
puts ("==> [info] Looking for #{options[:keyfile]}")
if File.file?(options[:keyfile])
config.vm.provision :shell, :inline => "echo -e '#{File.read(options[:keyfile])}' > '/home/vagrant/.ssh/GitKey'"
else
puts ("==> [error] The require RSA key: #{options[:keyfile]} does not exist, exiting.")
abort
end
end
Error
$ vagrant up ~/.ssh/github_rsa
The machine with the name '/Users/ehime/.ssh/github_rsa' was not found configured for
this Vagrant environment.
EDIT
Trying this a different way gives me some slightly more promising results
require 'optparse'
require 'ostruct'
....
options = OpenStruct.new
OptionParser.new do | opt |
opt.on('-v', '--version VERSION', 'Box version to load (not used currently)') { | o | options.version = o }
opt.on('-k', '--keyfile KEYFILE', 'Your Github authentication keyfile') { | o | options.keyfile = o }
opt.on('-b', '--boxfile BOXTYPE', 'Type of virtual appliance to load') { | o | options.boxtype = o }
end.parse!
Vagrant.configure("2") do | config |
puts ("==> [info] Looking for #{options.keyfile}")
if File.file?(options.keyfile)
config.vm.provision :shell, :inline => "echo -e '#{File.read(options.keyfile)}' > '/home/vagrant/.ssh/GitKey'"
else
puts ("==> [error] The require RSA key: #{options.keyfile} does not exist, exiting.")
abort
end
....
Gets me pretty close as well, but it needs the flags unset somehow so they don't conflict with vagrant. At least the help flag works
$ vagrant up -k /Users/ehime/.ssh/github_rsa
==> [info] Looking for /Users/ehime/.ssh/github_rsa
An invalid option was specified. The help for this command
is available below.
Usage: vagrant up [options] [name]
Options:
--[no-]provision Enable or disable provisioning
--provision-with x,y,z Enable only certain provisioners, by type.
--[no-]destroy-on-error Destroy machine if any fatal error happens (default to true)
--[no-]parallel Enable or disable parallelism if provider supports it
--provider PROVIDER Back the machine with a specific provider
-h, --help Print this help
Help
$ vagrant up -h
Usage: vagrant up [options] [name]
Options:
--[no-]provision Enable or disable provisioning
--provision-with x,y,z Enable only certain provisioners, by type.
--[no-]destroy-on-error Destroy machine if any fatal error happens (default to true)
--[no-]parallel Enable or disable parallelism if provider supports it
--provider PROVIDER Back the machine with a specific provider
-h, --help Print this help
Usage: vagrant [options]
-v, --version VERSION Box version to load (not used currently)
-k, --keyfile KEYFILE Your Github authentication keyfile
-b, --boxfile BOXTYPE Type of virtual appliance to load
The Vagrantfile is not executed directly so you cannot just pass in the arguments as you would with a normal script. vagrant looks for the file inside cwd() and bring it in.
Would go the route of the env vars or a template file which you generate before running vagrant.

Why does serverspec connect to the localhost instead of the remote host

My serverspec example, setup using serverspec-init, then I generated this simple test file ./spec/altspf01/sample_spec.rb
require 'spec_helper'
describe command( '/bin/hostname -s' ) do
its(:stdout) { should match /atlspf01/ }
end
I expect it to ssh to a remote host (atlspf01) and check its hostname (atlspf01). Instead it connects to the localhost (ltipc682).
1) Command "/bin/hostname -s" stdout should match /atlspf01/
Failure/Error: its(:stdout) { should match /atlspf01/ }
expected "ltipc682\n" to match /atlspf01/
Diff:
## -1,2 +1,2 ##
-/atlspf01/
+ltipc682
What have I done wrong?
All code here: https://gist.github.com/neilhwatson/a3f4a26ad8cf27d62307
Serverspec's specs should be run via rake. Otherwise, the spec doesn't know the target host.
However, if you wish to run it via rspec, you could use this workaround:
env TARGET_HOST='atlspf01' rspec spec/atlspf01/sample_spec.rb
Hope this helps.

Unable to connect remote host through net/ssh

This is pretty weird. I have my public key added at host machine. I can simply run
ssh -p <port> -l <username> hostt.com
which simply opens the remote shell. I can even run my capistrano scripts for the deployments on the same machine. But when i was trying connect with this following simple ruby script
require 'rubygems'
require 'net/ssh'
Net::SSH.start("hostt.com",
:port => <port>,
:username => <username>
) do |session|
puts session.pwd
end
it refuses immediately with the following exception:
`initialize': Connection refused - connect(2) (Errno::ECONNREFUSED)
Is there anything I'm missing here?
Appreciate your help.
Okay, now after a few days when I look back to the problem, I got a quick success with the following tweak:
Net::SSH.start("<host>", "<user>", :port => "<port>") { |ssh|
puts "logged in"
puts ssh.exec!("ls -l")
} rescue puts "failed to connect."
So the difference with the previous one is the username, which in this case is passed as the second argument rather than like an option key.
you probably need to provide the location of your SSH key, or a password to use with the username you provide in the SSH.start parameters. for the keys, you need to pass the map value as an array :keys => ["path_to_key"]. I'm not sure why the api is set up that way, but it is.

Resources