Skip to content

Commit

Permalink
DRAFT: Enable ACL
Browse files Browse the repository at this point in the history
Basically we partitially revert 793b120
and improve the hawk_invoke so that it works as non-root.

To try:
1) install expect
zypper in expect
2) add new user, for example alice
useradd -m -s /bin/bash -N -g 90 alice
passwd alice
3) enable /usr/sbin/ for both alice and hacluster
echo 'export PATH=$PATH:/usr/sbin/' >> ~/.bashrc
. ~/.bashrc
4) copy the hawk_invoke.sh into /usr/bin

To test if all setup correctly do
su - alice
hawk_invoke.sh alice <pass> 'cibadmin -Ql'
su - hacluster
hawk_invoke.sh hacluster linux 'cibadmin -Ql'

5) Do the usual routine (start hawk-apiserver and hawk). For example like
$ hawk-apiserver -key /etc/hawk/hawk.key -cert /etc/hawk/hawk.pem \
  -port7630 -config /etc/hawk/server.json
$ HAWK_ENV=development puma -C hawk/config/puma.rb
  • Loading branch information
Aleksei Burlakov committed Sep 15, 2023
1 parent 1ff135e commit e81ee7d
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 11 deletions.
14 changes: 13 additions & 1 deletion hawk/app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class ApplicationController < ActionController::Base
layout :detect_current_layout

around_action :inject_current_user
around_action :inject_current_pass
around_action :inject_current_cib
before_action :set_users_locale
before_action :set_current_home
Expand All @@ -23,6 +24,7 @@ class ApplicationController < ActionController::Base
helper_method :production_cib
helper_method :current_cib
helper_method :current_user
helper_method :current_pass

rescue_from Cib::CibError do |e|
respond_to do |format|
Expand Down Expand Up @@ -59,7 +61,7 @@ def production_cib
def current_cib
if current_user
@current_cib ||= begin
Cib.new(params[:cib_id] || production_cib, current_user, params[:debug] == "file", cookies[:stonithwarning].nil? || cookies[:stonithwarning] == true)
Cib.new(params[:cib_id] || production_cib, current_user, current_pass, params[:debug] == "file", cookies[:stonithwarning].nil? || cookies[:stonithwarning] == true)
end
end
end
Expand Down Expand Up @@ -96,6 +98,12 @@ def inject_current_user
yield
end

def inject_current_pass
current_controller = self
Thread.current[:current_pass] = proc { current_controller.send(:current_pass) }
yield
end

def set_users_locale
available = [params[:locale], cookies[:locale], default_locale].compact.first
I18n.locale = FastGettext.set_locale(available)
Expand Down Expand Up @@ -173,6 +181,10 @@ def current_user
@current_user ||= session[:username] || login_from_cookie
end

def current_pass
@current_pass ||= session[:password]
end

def is_god?
current_user == "hacluster" || current_user == "root"
end
Expand Down
2 changes: 2 additions & 0 deletions hawk/app/controllers/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def create
if @session.valid?
reset_session
session[:username] = @session.username
session[:password] = @session.password

# generate random value, store in attrd_updater (1024 Bits)
value = SecureRandom.hex(128)
Expand Down Expand Up @@ -66,6 +67,7 @@ def destroy
cookies.delete :hawk_remember_me_id
cookies.delete :hawk_remember_me_key
session[:username] = nil
session[:password] = nil
reset_session

respond_to do |format|
Expand Down
12 changes: 8 additions & 4 deletions hawk/app/lib/invoker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def initialize
# cleaned up further)
# Returns [out, err, exitstatus]
def run(*cmd)
out, err, status = Util.capture3(*cmd)
out, err, status = Util.run_as(current_user, current_pass, *cmd)
[out, fudge_error(status.exitstatus, err), status.exitstatus]
end

Expand Down Expand Up @@ -73,7 +73,7 @@ def crm_configure_load_update(cmd)
# Invoke cibadmin with command line arguments. Returns stdout as string,
# Raises NotFoundError, SecurityError or RuntimeError on failure.
def cibadmin(*cmd)
out, err, status = Util.capture3('cibadmin', *cmd)
out, err, status = Util.run_as(current_user, current_pass, 'cibadmin', *cmd)
case status.exitstatus
when 0
return out
Expand Down Expand Up @@ -105,7 +105,7 @@ def cibadmin_modify(xml)

# Used by the simulator
def crm_simulate(*cmd)
Util.capture3('crm_simulate', *cmd)
Util.run_as(current_user, current_pass, 'crm_simulate', *cmd)
end

private
Expand All @@ -132,7 +132,7 @@ def invoke_crm(input, *cmd)
end
cmd << { stdin_data: input }

out, err, status = Util.capture3('crm', *cmd)
out, err, status = Util.run_as(current_user, current_pass, 'crm', *cmd)
[out, fudge_error(status.exitstatus, err), status.exitstatus]
end

Expand All @@ -153,4 +153,8 @@ def fudge_error(exitstatus, stderr)
def current_user
Thread.current[:current_user].call
end

def current_pass
Thread.current[:current_pass].call
end
end
35 changes: 31 additions & 4 deletions hawk/app/lib/util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def numeric?(n)
# DON'T USE THIS FUNCTION DIRECTLY - it's subject to deadlocks e.g.:
# http://coldattic.info/shvedsky/pro/blogs/a-foo-walks-into-a-bar/posts/63
# Rather you should prefer capture3.
def popen3(*cmd)
def popen3(user, *cmd)
raise SecurityError, "Util::popen3 called with < 2 args" if cmd.length < 2
pw = IO::pipe # pipe[0] for read, pipe[1] for write
pr = IO::pipe
Expand All @@ -39,8 +39,13 @@ def popen3(*cmd)
STDERR.reopen(pe[1])
pe[1].close

# RORSCAN_INL: cmd always has > 1 elem, so safe from shell injection
exec(*cmd)
if user.to_s.strip.empty? or user == "hacluster" or user == "root"
# RORSCAN_INL: cmd always has > 1 elem, so safe from shell injection
exec(*cmd)
else
command = ['su', '-', user, 'sh', '-c', "#{cmd.join(" ")}"]
exec(*command)
end
}
wait_thr = Process.detach(pid)

Expand Down Expand Up @@ -73,7 +78,7 @@ def capture3(*cmd)
end
Rails.logger.debug "Executing `#{cmd.join(' ').inspect}` through `capture3`"
stdin_data = opts.delete(:stdin_data) || ''
Util.popen3(*cmd) {|i, o, e, t|
Util.popen3(nil, *cmd) {|i, o, e, t|
out_reader = Thread.new { o.read }
err_reader = Thread.new { e.read }
i.write stdin_data
Expand All @@ -83,6 +88,28 @@ def capture3(*cmd)
end
module_function :capture3

def run_as(user, pass, *cmd)
if Hash === cmd.last
opts = cmd.pop.dup
else
opts = {}
end
Rails.logger.debug "Executing `#{cmd.join(' ').inspect}` as `#{user}` through `run_as`"
stdin_data = opts.delete(:stdin_data) || ''
Util.popen3(user, *cmd) {|i, o, e, t|
out_reader = Thread.new { o.read }
err_reader = Thread.new { e.read }
if not user.to_s.strip.empty? and user != "hacluster" and user != "root"
i.write pass
i.write "\n"
end
i.write stdin_data
i.close
[out_reader.value, err_reader.value, t.value]
}
end
module_function :run_as

def ensure_home_for(user)
old_home = ENV['HOME']
ENV['HOME'] = begin
Expand Down
4 changes: 2 additions & 2 deletions hawk/app/models/cib.rb
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ def warning(msg, additions = {})
error(msg, :warning, additions)
end

def initialize(id, user, use_file = false, stonithwarning = false)
def initialize(id, user, pass, use_file = false, stonithwarning = false)
Rails.logger.debug "Cib.initialize #{id}, #{user}, #{use_file}"

if use_file
Expand Down Expand Up @@ -511,7 +511,7 @@ def initialize(id, user, use_file = false, stonithwarning = false)
init_offline_cluster id, user, use_file
return
end
out, err, status = Util.capture3('cibadmin', '-Ql')
out, err, status = Util.run_as(user, pass, 'cibadmin', '-Ql')
case status.exitstatus
when 0
@xml = REXML::Document.new(out)
Expand Down

0 comments on commit e81ee7d

Please sign in to comment.