From: Goldwyn Rodrigues <rgoldwyn@suse.com> The apparmor_ui_dialog communicates with aa-logprof in JSON. Each dialog is converted to a yast dialog for input from the user and returns the actions performed in yast in the form of JSON response. An extra opendialog has been used to indicate the end of the logprof execution. Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> --- src/clients/apparmor.rb | 1 + src/clients/logprof.rb | 94 +++++++++++++ src/lib/apparmor/apparmor_ui_dialog.rb | 243 +++++++++++++++++++++++++++++++++ 3 files changed, 338 insertions(+) create mode 100644 src/clients/logprof.rb create mode 100644 src/lib/apparmor/apparmor_ui_dialog.rb diff --git a/src/clients/apparmor.rb b/src/clients/apparmor.rb index 1e6d7e3..7c2ed6f 100644 --- a/src/clients/apparmor.rb +++ b/src/clients/apparmor.rb @@ -70,6 +70,7 @@ module Yast [ # Selection box items Item(Id("apparmor-settings"), _("Settings"), true), + Item(Id("logprof"), _("Scan Audit logs")), Item(Id("AA_AddProfile"), _("Manually Add Profile")) ] ), diff --git a/src/clients/logprof.rb b/src/clients/logprof.rb new file mode 100644 index 0000000..95cbf5c --- /dev/null +++ b/src/clients/logprof.rb @@ -0,0 +1,94 @@ + +require "open3" +require "json" +require "yast" +require "apparmor/apparmor_ui_dialog" + +Yast.import "UI" +Yast.import "Label" +Yast.import "Popup" + +module AppArmor + class LogProf + LOGPROF = "/usr/sbin/aa-logprof" + attr_reader :logfile, :raw + include Yast::UIShortcuts + include Yast::Logger + include Yast::I18n + + def initialize(logfile="") + @logfile = logfile + log.info "Logfile is #{logfile}." + end + + def execute() + cmd = "#{LOGPROF} --json" + if @logfile.length > 0 + cmd += " -f #{@logfile}" + end + log.info "Executing #{cmd}" + IO.popen(cmd, "r+") do |f| + f.sync = true + f.each do | line | + log.info "aa-logprof lines #{line}." + if !line.start_with?("{") + next + end + hm = JSON.parse(line) + log.info "aa-logprof hashmap #{hm}." + l = get_dialog(hm) + r = l.run + if !r.nil? + f.puts r.to_json + f.flush + end + end + end + + Yast::UI.OpenDialog( + Opt(:decorated, :defaultsize), + VBox( + Label(_("No more records in logfile #{@logfile} to process")), + VSpacing(2), + HBox( + HStretch(), + HWeight(1, PushButton(Id(:ok), Yast::Label.OKButton)), + HStretch() + ) + ) + ) + Yast::UI.UserInput() + Yast::UI.CloseDialog() + end + + private + def get_dialog(hm) + case hm["dialog"] + when "yesno" + return YesNoDialog.new(hm) + when "yesnocancel" + return YesNoCancelDialog.new(hm) + when "info" + return InfoDialog.new(hm) + when "getstring" + return GetStringDialog.new(hm) + when "getfile" + return GetFileDialog.new(hm) + when "getstring" + return PromptDialog.new(hm) + when "promptuser" + return PromptDialog.new(hm) + when "apparmor-json-version" + return AAJSONVersion.new(hm) + else + Yast::Report.Error(_("Unknown Dialog %s returned by apparmor") % hm["dialog"]) + return nil + end + end + end +end + +#AppArmor::LogProf.new.execute +AppArmor::LogProf.new("/var/log/audit/audit.log").execute + + diff --git a/src/lib/apparmor/apparmor_ui_dialog.rb b/src/lib/apparmor/apparmor_ui_dialog.rb new file mode 100644 index 0000000..8045301 --- /dev/null +++ b/src/lib/apparmor/apparmor_ui_dialog.rb @@ -0,0 +1,243 @@ +# This file has all the dialog translations/representations +# which come from the apparmor's json +# show_respond() must return what would be communicated back to +# the program in the form of a hash map. It could be nil if no +# data must be written. + +require "yast" + +Yast.import "UI" +Yast.import "Label" +Yast.import "Report" +Yast.import "Popup" + +module AppArmor + class YesNoDialog + include Yast::UIShortcuts + include Yast::I18n + def initialize(hm) + @data = hm["text"] + @map = Hash.new + @map["dialog"] = "yesno" + end + + def run() + Yast::UI.OpenDialog( + Opt(:decorated, :defaultsize), + VBox( + Label(@data), + VSpacing(1), + HBox( + HStretch(), + HWeight(1, PushButton(Id(:y), _("Yes"))), + HSpacing(2), + HWeight(1, PushButton(Id(:n), _("No"))), + ) + ) + ) + case Yast::UI.UserInput + when :y + @map["response"] = "yes" + @map["response_key"] = "y" + when :n + @map["response"] = "no" + @map["response_key"] = "n" + end + Yast::UI.CloseDialog + return @map + end + end + + class YesNoCancelDialog + include Yast::UIShortcuts + include Yast::I18n + include Yast::Logger + def initialize(hm) + @data = hm["data"] + @map = Hash.new + @map["dialog"] = "yesnocancel" + end + + def run() + Yast::UI.OpenDialog( + Opt(:decorate, :defaultsize), + VBox( + Label(@data), + VSpacing(0.3), + HBox( + HWeight(1, PushButton(Id(:y), _("Yes"))), + HStretch(), + HWeight(1, PushButton(Id(:n), _("No"))), + HStretch(), + HWeight(1, PushButton(Id(:c), Label.CancelButton)) + ) + ) + ) + case Yast::UI.UserInput + when :y + @map["response"] = "yes" + @map["response_key"] = "y" + when :n + @map["response"] = "no" + @map["response_key"] = "n" + when :c + @map["response"] = "cancel" + @map["response_key"] = "c" + end + Yast::UI.CloseDialog + return @map + end + end + + class InfoDialog + include Yast::UIShortcuts + include Yast::I18n + include Yast::Logger + def initialize(hm) + log.info "Hash map #{hm}" + end + def run() + return nil + end + end + + class GetStringDialog + include Yast::UIShortcuts + include Yast::I18n + include Yast::Logger + def initialize(hm) + log.info "Hash map #{hm}" + @map = Hash.new + @map["dialog"] = "getstring" + end + def run() + Yast::UI.OpenDialog( + Opt(:decorate, :defaultsize), + VBox( + Inputfield(Id(:str), @text), + PushButton("&OK") + ) + ) + str = Yast::UI.QueryWidget(Id(:str), :Value) + Yast::UI.UserInput() + Yast::UI.CloseDialog() + @map["response"] = str + return @map + end + end + + class GetFileDialog + include Yast::UIShortcuts + include Yast::I18n + include Yast::Logger + def initialize(hm) + log.info "Hash map #{hm}" + @map = Hash.new + @map["dialog"] = "getfile" + end + def run() + filename = Yast::UI.AskForExistingFile("/etc/apparmor.d", "*", _("Choose a file")) + if !filename.nil? + @map["response"] = filename + end + return @map + end + + end + + class PromptDialog + include Yast::UIShortcuts + include Yast::I18n + include Yast::Logger + include Yast + def initialize(hm) + log.info "Hash map #{hm}" + @map = Hash.new + @map["dialog"] = "promptuser" + @title = hm["title"] + @headers = hm["headers"] + @explanation = hm["explanation"] + @options = hm["options"] + @menu_items = hm["menu_items"] + end + def run() + @map["selected"] = 0 + # Display the dynamic widget + + UI.OpenDialog( + Opt(:decorated, :defaultsize), + VBox( + *explanation_label, + *header_labels, + *options_radiobtns, + *menubtns + ) + ) + + @map["response_key"] = Yast::UI.UserInput() + selected = Yast::UI.QueryWidget(:options, :CurrentButton) + @map["selected"] = selected.to_i + return @map + end + private + + def explanation_label + box = VBox() + box[box.size] = VSpacing(1) + if !@explanation.nil? + box[box.size] = Label(@explanation) + end + box + end + + def header_labels + box = VBox() + @headers.each do | key, value | + box[box.size] = Label(key.to_s + ": " + value.to_s) + box[box.size] = VSpacing(1) + end + box + end + + def options_radiobtns + box = VBox() + @options.each_with_index do | opt, i| + box[box.size] = RadioButton(Id(i.to_s), opt, i==0) + box[box.size] = VSpacing(1) + end + VBox(RadioButtonGroup(Id(:options), box)) + end + def menu_to_text_key(menu) + ind = menu.index('(') + key = menu[ind+1, 1].downcase + text = menu.delete('(').delete(')').delete('[').delete(']') + return text, key + end + def menubtns + box = HBox() + @menu_items.each do | menu | + text, key = menu_to_text_key(menu) + box[box.size] = HWeight(1, PushButton(Id(key.to_s), text)) + box[box.size] = HSpacing(1) + end + VBox(box) + end + end + + class AAJSONVersion + include Yast::I18n + include Yast::Logger + AA_JSON = 2.12 + def initialize(hm) + log.info "Hash map #{hm}" + @json_version = hm["data"].to_f + if (@json_version > AA_JSON) + Yast::Report.Error(_("Apparmor JSON version %s is greater than %0.2f" % [@json_version, AA_JSON])) + end + end + def run() + return nil + end + end +end + -- 2.12.3 -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org To contact the owner, e-mail: yast-devel+owner@opensuse.org