ruby execute bash command with variables - ruby

I need to execute a Bash command in a Ruby script. There are about 6 ways to do this according to "6 Ways to Run Shell Commands in Ruby" by Nate Murray and a few other googled sources.
print "enter myid: "
myID = gets
myID = myID.downcase
myID = myID.chomp
print "enter host: "
host = gets
host = host.downcase
host = host.chomp
print "winexe to host: ",host,"\n"
command = "winexe -U domain\\\\",ID," //",host," \"cmd\""
exec command

For what it's worth you can actually chain those methods, and puts will print a newline for you, so this could just be:
print "enter myid: "
myID = STDIN.gets.downcase.chomp
print "enter host: "
host = STDIN.gets.downcase.chomp
puts "winexe to host: #{host}"
command = "winexe -U dmn1\\\\#{myID} //#{host} \"cmd\""
exec command

It looks like there may have been trouble with how you were putting your command string together.
Also, I had to refer to STDIN directly.
# Minimal changes to get it working:
print "enter myid: "
myID = STDIN.gets
myID = myID.downcase
myID = myID.chomp
print "enter host: "
host = STDIN.gets
host = host.downcase
host = host.chomp
print "winexe to host: ",host,"\n"
command = "echo winexe -U dmn1\\\\#{myID} //#{host} \"cmd\""
exec command
Compact version:
print "enter myid: "
myID = STDIN.gets.downcase.chomp
print "enter host: "
host = STDIN.gets.downcase.chomp
puts "winexe to host: #{host}"
exec "echo winexe -U dmn1\\\\#{myID} //#{host} \"cmd\""
Last two lines with printf style:
puts "winexe to host: %s" % host
exec "echo winexe -U dmn1\\\\%s //%s \"cmd\"" % [myID, host]
Last two lines with plus string concatenation:
puts "winexe to host: " + host
exec "echo winexe -U dmn1\\\\" + myID + " //" + host + " \"cmd\""
Last two lines with C++ style append:
puts "winexe to host: " << host
exec "echo winexe -U dmn1\\\\" << myID << " //" << host << " \"cmd\""

Related

Insert bcrypt hash into specific line in file using bash

I need to update an application configuration by inserting bcrypt hash into file config.yml at specific lines.
echo -e "$Enter password for user1"
read -p ": " user1_pass
echo -e "$Enter password for user2"
read -p ": " user2_pass
user1_hash=$(htpasswd -bnBC 10 "" $user1_pass | tr -d ':\n')
user2_hash=$(htpasswd -bnBC 10 "" $user2_pass | tr -d ':\n')
$user1_hash should be placed inline 2 and $user2_hash inline 7.
config.yml
user1:
hash: "$2y$12$shEKzuVfogdZFbbraSqhwOOh96hfxe1NzLQbpmHJvgDUeRfRrkf3a"
reserved: "true"
roles: "user"
user2:
hash: "$2y$12$Fkc5GAp9Za5caIfHjBgNQ.jNEss0SJfCLTlm9EhAcjzPVy.kLriBa"
reserved: "true"
roles: "user"
What is the best approach to do that using bash?
You can edit the file using Ruby :
#!/usr/bin/ruby
require 'yaml'
obj = YAML.load_file('config.yml')
bcrypt_hash='$2y$12$shEKzuVfogdZFbbraSqhwOOh96hfxe1NzLQbpmHJvgDUeRfRrkf3a'
obj['user1']['hash'] = bcrypt_hash
obj['user2']['hash'] = bcrypt_hash
puts YAML.dump(obj)
This will output :
... More yml content
user1:
hash: "$2y$12$shEKzuVfogdZFbbraSqhwOOh96hfxe1NzLQbpmHJvgDUeRfRrkf3a"
user2:
hash: "$2y$12$shEKzuVfogdZFbbraSqhwOOh96hfxe1NzLQbpmHJvgDUeRfRrkf3a"
... More yml content
Hope it helps!
Use the keyword echo to write into the file
echo -e "$Enter password for user1"
read -p ": " user1_pass
echo -e "$Enter password for user2"
read -p ": " user2_pass
user1_hash=$(htpasswd -bnBC 10 "" $user1_pass | tr -d ':\n')
user2_hash=$(htpasswd -bnBC 10 "" $user2_pass | tr -d ':\n')
echo "user1:" > config.yml
echo " hash: " + $user1_hash >> config.yml
echo "user2:" >> config.yml
echo " hash: " + $user2_hash >> config.yml
the contents of config.yml file being
user1:
hash: + $2y$10$7S0fC4wTqAfm9ytJ5BquC.3KITsqLoqPXHyj3mzgXdvw10TRIybni
user2:
hash: + $2y$10$jcYMrOsdIzwR3AlSONNfCuc.B5AoGVV4i31KSsx0PLlpn17issJfe

Removing an item from an array when chef-client is executed

I am using the firewalld cookbook and having difficulty rewriting the provider code to exclude subnets missing from an array. Below is what the current firewalld provider code looks like. Can some assist with this?
use_inline_resources
action :add do
e = execute "add port #{new_resource.name} to zone" do
not_if "firewall-cmd #{zone} --query-rich-rule=\"#{rich_rule}\"
command(<<-EOC)
firewall-cmd #{zone} --add-rich-rule="#{rich_rule}"
firewall-cmd --permanent #{zone} --add-rich-rule="#{rich_rule}"
EOC
end
new_resource.updated_by_last_action(e.updated_by_last_action?)
end
action :remove do
e = execute "remove port #{new_resource.name} from zone" do
only_if "firewall-cmd #{zone} --query-rich-rule=\"#{rich_rule}\""
command(<<-EOC)
firewall-cmd #{zone} --remove-rich-rule="#{rich_rule}"
firewall-cmd --permanent #{zone} --remove-rich-rule="#{rich_rule}"
EOC
end
new_resource.updated_by_last_action(e.updated_by_last_action?)
end
def zone
new_resource.zone ? "--zone=#{new_resource.zone}" : ''
end
def rich_rule
cmd = "rule "
cmd += "family='#{new_resource.family}' " if new_resource.family
cmd += "source address='#{new_resource.source_address}' " if new_resource.source_address
cmd += "destination address='#{new_resource.destination_address}' " if new_resource.destination_address
cmd += "service name='#{new_resource.service_name}' " if new_resource.service_name
cmd += "port port='#{new_resource.port_number}' protocol='#{new_resource.port_protocol}' " if new_resource.port_number
cmd += "log " if new_resource.log_prefix || new_resource.log_level || new_resource.limit_value
cmd += "prefix='#{new_resource.log_prefix}' " if new_resource.log_prefix
cmd += "level='#{new_resource.log_level}' " if new_resource.log_level
cmd += "limit value='#{new_resource.limit_value}' " if new_resource.limit_value
cmd += new_resource.firewall_action if new_resource.firewall_action
cmd end
My recipe currently looks like this
node['cookbook']['iptables']['subnets'].each do |firewall|
firewalld_rich_rule firewall do
zone firewall["public"]
family firewall["ipv4"]
source_address firewall
firewall_action firewall["accept"]
action :add
end
end
My attributes currently look like this
default["cookbook"]["iptables"]["subnets"] = ["172.16.2.0/24","192.168.1.1/24","10.10.10.0/24"]
The code is currently working as expected. In other words, when i run the cookbook, it populates firewalld with subnets in the attribute array. However when i delete one of the subnets and run the cookbook, it doesn't delete the excluded subnet. Is there a way to write this whereby it automatically deletes any rich rule subnet not in the array?

Expect-like functionality to IO.gets?

For example, if I wanted to automate authorizing a hex user. Something like
mix hex.user auth
#!/usr/bin/expect -f
expect "Username: "
send -- "$HEX_USERNAME\r"
expect "Password: "
send -- "$HEX_PASSWORD\r"
mix hex.user auth asks for Username: and Password: but I don't think expect works for this
Given the following script:
u = IO.gets("Username: ") |> String.strip
p = IO.gets("Password: ") |> String.strip
IO.puts ""
IO.puts "#{u} - #{p}"
You can pass input like this:
$ export HEX_USERNAME="hexuser"
$ export HEX_PASSWORD="hexpass"
$ echo "$HEX_USERNAME\n$HEX_PASSWORD" | elixir test.exs
Username: Password:
hexuser - hexpass
So, you could use
echo "$HEX_USERNAME\n$HEX_PASSWORD" | mix hex.user auth

VBS expected statement error

I keep getting a Error Expected statement. Code 800A0400. Line 1, char 1. What am I doing wrong?
My code,
# $language = "VBScript"
# $interface = "1.0"
' Connect to an SSH server using the SSH2 protocol. Specify the
' username and password and hostname on the command line as well as
' some SSH2 protocol specific options.
Sub Main
Dim host
host = "ssh.google.com"
Dim user
user = "userinfo"
' Prompt for a password instead of embedding it in a script...
'
Dim passwd
passwd = crt.Dialog.Prompt("Enter password for " & host, "Login", "", True)
' Build a command-line string to pass to the Connect method.
'
cmd = "/SSH2 /L " & user & " /PASSWORD " & passwd & " /C 3DES /M MD5 " & host
crt.Session.Connect cmd
End Sub
The "comment to end of line" marker in VBScript is the single quote ', not #. So change
# $language = "VBScript"
# $interface = "1.0"
to
' $language = "VBScript"
' $interface = "1.0"
(Other possible problems: do you call Sub main? Where does crt come from?)

Ruby $stdin.gets without showing chars on screen

I want to ask users to type in a password, but I don't want the chars to appear on screen as they type.
How do I do this in Ruby?
You can use the STDIN.noecho method from the IO/console module:
require 'io/console'
pw = STDIN.noecho(&:gets).chomp
If you're on a system with stty:
`stty -echo`
print "Password: "
pw = gets.chomp
`stty echo`
puts ""
There is a gem for such user interaction: highline.
password = ask("Password: ") { |q| q.echo = false }
Or even:
password = ask("Password: ") { |q| q.echo = "*" }
You want to make sure your code is idempotent... other solutions listed here assume you want to exit this chunk of functionality with echo turned back on. Well, what if it was turned off before entering the code, and it's expected to stay off?
stty_settings = %x[stty -g]
print 'Password: '
begin
%x[stty -echo]
password = gets
ensure
%x[stty #{stty_settings}]
end
puts
print 'regular info: '
regular_info = gets
puts "password: #{password}"
puts "regular: #{regular_info}"
This is solution for UNIX systems:
begin
system "stty -echo"
print "Password: "; pass1 = $stdin.gets.chomp; puts "\n"
print "Password (repeat): "; pass2 = $stdin.gets.chomp; puts "\n"
if pass1 == pass2
# DO YOUR WORK HERE
else
STDERR.puts "Passwords do not match!"
end
ensure
system "stty echo"
end
Similar answer as glenn but more complete: http://dmathieu.com/articles/development/ruby-console-ask-for-a-password/

Resources