Commit 7d245cb1 authored by Cool Fire's avatar Cool Fire

Can now handle request from CLI tool

parent 99af00cb
...@@ -6,8 +6,10 @@ ...@@ -6,8 +6,10 @@
"pass":"rabbitmq_pass", "pass":"rabbitmq_pass",
"channel_commands":"ServerName", "channel_commands":"ServerName",
"channel_results":"Results", "channel_results":"Results",
"channel_requests":"Requests",
"private_keyfile":"config/private.pem", "private_keyfile":"config/private.pem",
"encryption_pass":"password_for_private.pem", "encryption_pass":"password_for_private.pem",
"api_url":"http://localhost:3000/api/index", "api_url_results":"http://localhost:3000/api/index",
"api_url_requests":"http://localhost:3000/api/jobrequest",
"api_pass":"some_secret_key" "api_pass":"some_secret_key"
} }
\ No newline at end of file
...@@ -11,6 +11,11 @@ class ApiController < ApplicationController ...@@ -11,6 +11,11 @@ class ApiController < ApplicationController
def jobrequest def jobrequest
@result = "" @result = ""
if !check_key(params[:key])
@result = "Invalid key"
return @result
end
# Check if this needs to be a request or if it can be done directly # Check if this needs to be a request or if it can be done directly
if(autorun(params[:command])) if(autorun(params[:command]))
@job = Job.new() @job = Job.new()
......
...@@ -11,14 +11,17 @@ module JobrequestsHelper ...@@ -11,14 +11,17 @@ module JobrequestsHelper
'httpd_logs_enable' => '', 'httpd_logs_enable' => '',
'httpd_logs_disable' => '' 'httpd_logs_disable' => ''
} }
return autorun_jobs.has_key? j return autorun_jobs.has_key? j
end end
def update_job(j) def check_key(key)
# Check key
config = loadconfig() config = loadconfig()
if(config['api_pass'] != j[:key]) return config['api_pass'] == key
end
def update_job(j)
if !check_key(j[:key])
return "Invalid key" return "Invalid key"
end end
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
<td><%= showtime(job.timestampstarted) %></td> <td><%= showtime(job.timestampstarted) %></td>
<td><%= showtime(job.timestampcompleted) %></td> <td><%= showtime(job.timestampcompleted) %></td>
<td><%= link_to job.server.shortname, server_path(job.server) %></td> <td><%= link_to job.server.shortname, server_path(job.server) %></td>
<td><%= link_to job.command.name, job_path(job) %></td> <td><%= link_to job.command.name, jobrequest_path(job) %></td>
<td><%= job.args %></td> <td><%= job.args %></td>
<td><%= job.result %></td> <td><%= job.result %></td>
</tr> </tr>
......
...@@ -7,8 +7,9 @@ require 'json' ...@@ -7,8 +7,9 @@ require 'json'
require 'optparse' require 'optparse'
require 'openssl' require 'openssl'
require 'time' require 'time'
require "net/http" require 'net/http'
require "uri" require 'uri'
require 'thread'
# Function to report errors (to syslog or to stderr) # Function to report errors (to syslog or to stderr)
def report(message) def report(message)
...@@ -57,62 +58,119 @@ else ...@@ -57,62 +58,119 @@ else
raise "Config file does not exist: #{options[:config]}" raise "Config file does not exist: #{options[:config]}"
end end
# Start up RabbitMQ
conn = Bunny.new(
:host => config['host'],
:user => config['user'],
:password => config['pass'],
)
conn.start
ch = conn.create_channel
q = ch.queue(config['channel_results'])
# Read private key so we can decrypt messages
private_key = OpenSSL::PKey::RSA.new(File.read(config['private_keyfile']), config['encryption_pass'])
# Check if we should be daemonized # Check if we should be daemonized
if(options[:daemon] || config['daemonize']) if(options[:daemon] || config['daemonize'])
puts "Worker running in background." puts "Worker running in background."
@daemonize = true @daemonize = true
Process.daemon Process.daemon
# Start syslog # Start syslog
Syslog.open("result_listener", Syslog::LOG_PID, Syslog::LOG_DAEMON | Syslog::LOG_LOCAL3) Syslog.open("result_listener", Syslog::LOG_PID, Syslog::LOG_DAEMON | Syslog::LOG_LOCAL3)
end end
def results(options, config)
# Start up RabbitMQ
conn = Bunny.new(
:host => config['host'],
:user => config['user'],
:password => config['pass'],
)
conn.start
ch = conn.create_channel
q = ch.queue(config['channel_results'])
# Read private key so we can decrypt messages
private_key = OpenSSL::PKey::RSA.new(File.read(config['private_keyfile']), config['encryption_pass'])
# Start waiting for messages
q.subscribe(:block => true) do |delivery_info, properties, payload|
# Try to decrypt and parse message
begin
message = JSON.parse(private_key.private_decrypt(payload))
# Check if the message seems to be authentic and sane
# and attempt to execute it.
if(Time.now.to_i > message['timestamp'] + config['max_skew'])
report("Rejected message #{message['id']}: Timestamp too old. (#{delivery_info[:channel].connection.host})")
else
puts message
uri = URI.parse(config['api_url_results'])
response = Net::HTTP.post_form(uri,
{
'id' => message['id'],
'timestamp' => message['timestamp'],
'exitcode' => message['exitcode'],
'message' => message['message'],
'key' => config['api_pass']
}
)
puts response.body
end
rescue Exception => e
report("Could not decode message. (#{delivery_info[:channel].connection.host})")
end
end
conn.close
end
# Start waiting for messages def requests(options, config)
q.subscribe(:block => true) do |delivery_info, properties, payload| # Start up RabbitMQ
conn = Bunny.new(
# Try to decrypt and parse message :host => config['host'],
begin :user => config['user'],
message = JSON.parse(private_key.private_decrypt(payload)) :password => config['pass'],
)
# Check if the message seems to be authentic and sane conn.start
# and attempt to execute it.
if(Time.now.to_i > message['timestamp'] + config['max_skew']) ch = conn.create_channel
report("Rejected message #{message['id']}: Timestamp too old. (#{delivery_info[:channel].connection.host})") q = ch.queue(config['channel_requests'])
else
puts message
uri = URI.parse(config['api_url']) # Read private key so we can decrypt messages
response = Net::HTTP.post_form(uri, private_key = OpenSSL::PKey::RSA.new(File.read(config['private_keyfile']), config['encryption_pass'])
{
'id' => message['id'], # Start waiting for messages
'timestamp' => message['timestamp'], q.subscribe(:block => true) do |delivery_info, properties, payload|
'exitcode' => message['exitcode'],
'message' => message['message'], # Try to decrypt and parse message
'key' => config['api_pass'] begin
} message = JSON.parse(private_key.private_decrypt(payload))
)
puts response.body # Check if the message seems to be authentic and sane
# and attempt to execute it.
if(Time.now.to_i > message['timestamp'] + config['max_skew'])
report("Rejected message #{message['id']}: Timestamp too old. (#{delivery_info[:channel].connection.host})")
else
puts message
uri = URI.parse(config['api_url_requests'])
response = Net::HTTP.post_form(uri,
{
'server_id' => message['server'],
'command_id' => message['command'],
'args' => message['args'],
'user' => message['user'],
'email' => message['email'],
'key' => config['api_pass']
}
)
puts response.body
end
rescue Exception => e
puts e.to_s
report("Could not decode message. (#{delivery_info[:channel].connection.host})")
end end
rescue Exception => e
report("Could not decode message. (#{delivery_info[:channel].connection.host})")
end end
conn.close
end end
conn.close res = Thread.new { results( options, config ) }
\ No newline at end of file req = Thread.new { requests( options, config ) }
res.join
req.join
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment