From: Goldwyn Rodrigues <rgoldwyn@suse.com> Handles the profiles using JSON output of aa-status. This replaces the earlier way of handling profiles. Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> --- src/clients/AA_EditProfile.rb | 129 ---------------------- src/clients/apparmor-settings.rb | 3 +- src/clients/apparmor.rb | 1 - src/clients/profiles.rb | 111 +++++++++++++++++++ src/lib/apparmor/profiles.rb | 227 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 340 insertions(+), 131 deletions(-) delete mode 100644 src/clients/AA_EditProfile.rb create mode 100644 src/clients/profiles.rb create mode 100644 src/lib/apparmor/profiles.rb diff --git a/src/clients/AA_EditProfile.rb b/src/clients/AA_EditProfile.rb deleted file mode 100644 index a616143..0000000 --- a/src/clients/AA_EditProfile.rb +++ /dev/null @@ -1,129 +0,0 @@ -# encoding: utf-8 - -# *************************************************************************** -# -# Copyright (c) 2002 - 2012 Novell, Inc. -# All Rights Reserved. -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of version 2 of the GNU General Public License as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, contact Novell, Inc. -# -# To contact Novell about this file by physical or electronic mail, -# you may find current contact information at www.novell.com -# -# *************************************************************************** -module Yast - class AAEditProfileClient < Client - def main - Yast.import "UI" - Yast.import "Wizard" - Yast.import "Popup" - Yast.import "Label" - Yast.import "Sequencer" - Yast.include self, "apparmor/apparmor_packages.rb" - Yast.include self, "apparmor/apparmor_profile_check.rb" - Yast.include self, "apparmor/profile_dialogs.rb" - textdomain "yast2-apparmor" - - # Globalz - - @profiles = nil - - - - # - # YEAH BABY RUN BABY RUN - # - @ret = nil - - # no command line support #269891 - if Ops.greater_than(Builtins.size(WFM.Args), 0) - Yast.import "CommandLine" - CommandLine.Init({}, WFM.Args) - return deep_copy(@ret) - end - - return deep_copy(@ret) if !installAppArmorPackages - - return deep_copy(@ret) if !checkProfileSyntax - - - @ret = MainSequence() - deep_copy(@ret) - end - - def Reread - @profiles = Convert.to_map(SCR.Read(path(".apparmor_profiles"), "all")) - :next - end - - - def MainSequence - # - # Read the profiles from the SCR agent - Reread() - - aliases = { - "showProfile" => lambda do - DisplayProfileForm( - Ops.get_string(@Settings, "CURRENT_PROFILE", ""), - false - ) - end, - "showHat" => lambda do - DisplayProfileForm(Ops.get_string(@Settings, "CURRENT_HAT", ""), true) - end, - "chooseProfile" => lambda do - SelectProfileForm( - @profiles, - _("Select a listed profile and press Edit to edit it."), - _("Edit Profile - Choose profile to edit"), - "apparmor_edit_profile" - ) - end, - "reread" => lambda { Reread() } - } - - sequence = { - "ws_start" => "chooseProfile", - "chooseProfile" => { - :abort => :abort, - :edit => "showProfile", - :reread => "reread", - :next => :next - }, - "showProfile" => { - :abort => :abort, - :next => "reread", - :showhat => "showHat", - :finish => :next - }, - "reread" => { :next => "chooseProfile" }, - "showHat" => { - :abort => :abort, - :next => "showProfile", - :finish => :next - } - } - - Wizard.CreateDialog - Wizard.SetTitleIcon("apparmor_edit_profile") - ret = Sequencer.Run(aliases, sequence) - Wizard.CloseDialog - @Settings = Builtins.remove(@Settings, "CURRENT_PROFILE") - @Settings = Builtins.remove(@Settings, "PROFILE_MAP") - deep_copy(ret) - end - end -end - -Yast::AAEditProfileClient.new.main diff --git a/src/clients/apparmor-settings.rb b/src/clients/apparmor-settings.rb index 2b2d3f2..d3f6d1a 100644 --- a/src/clients/apparmor-settings.rb +++ b/src/clients/apparmor-settings.rb @@ -21,6 +21,7 @@ # *************************************************************************** require "yast" +require "apparmor/profiles" Yast.import "UI" Yast.import "Label" @@ -77,7 +78,7 @@ module AppArmor loop do case Yast::UI.UserInput when :modeconf - break + AppArmor::ProfilesDialog.new.run when :quit break end diff --git a/src/clients/apparmor.rb b/src/clients/apparmor.rb index 63e8874..1e6d7e3 100644 --- a/src/clients/apparmor.rb +++ b/src/clients/apparmor.rb @@ -70,7 +70,6 @@ module Yast [ # Selection box items Item(Id("apparmor-settings"), _("Settings"), true), - Item(Id("AA_EditProfile"), _("Manage Existing Profiles")), Item(Id("AA_AddProfile"), _("Manually Add Profile")) ] ), diff --git a/src/clients/profiles.rb b/src/clients/profiles.rb new file mode 100644 index 0000000..06c6e8a --- /dev/null +++ b/src/clients/profiles.rb @@ -0,0 +1,111 @@ + +require "apparmor/profiles" +Yast.import "UI" +Yast.import "Label" +Yast.import "Popup" + +class ProfilesDialog + include Yast::UIShortcuts + include Yast::I18n + include Yast::Logger + + def initialize + @profiles = Apparmor::Profiles.new + @active = true + end + + def run + return unless create_dialog + + begin + return event_loop + ensure + close_dialog + end + end + +private + def create_dialog + Yast::UI.OpenDialog( + Opt(:decorated, :defaultsize), + VBox( + #Header + Heading(_("Profile List")), + # Active profiles + Left( + CheckBox(Id(:active_only), Opt(:notify), _("Show Active only"), @active) + ), + VSpacing(0.4), + # Profile List + table, + VSpacing(0.3), + # Footer buttons + HBox( + HWeight(1, PushButton(Id(:toggle), _("Toggle mode"))), + HStretch(), + HWeight(1, PushButton(Id(:add), Yast::Label.AddButton)), + HStretch(), + HWeight(1, PushButton(Id(:edit), Yast::Label.EditButton)), + HStretch(), + HWeight(1, PushButton(Id(:finish), Yast::Label.FinishButton)) + ) + ) + ) + end + + def table + headers = Array[_("Name"), _("Mode"), _("PID")] + Table( + Id(:entries_table), + Opt(:keepSorting), + Header(*headers), + table_items + ) + end + + def table_items + if @active + profs = @profiles.active + else + profs = @profiles.all + end + arr = Array.new + profs.each do | n, pr | + arr.push(pr.to_array) + end + arr.map { |i| Item(*i) } + end + + def redraw_table + Yast::UI.ChangeWidget(Id(:entries_table), :Items, table_items) + end + + def event_loop + loop do + case Yast::UI.UserInput + when :active_only + @active = Yast::UI.QueryWidget(Id(:active_only), :Value) + redraw_table + when :cancel + break + when :toggle + selectedItem = Yast::UI.QueryWidget(Id(:entries_table), :CurrentItem) + log.info "Toggling #{selectedItem}" + @profiles.toggle(selectedItem) + redraw_table + when :edit + break + when :finish + break + end + end + end + + def close_dialog + Yast::UI.CloseDialog + end +end + +ProfilesDialog.new.run + + diff --git a/src/lib/apparmor/profiles.rb b/src/lib/apparmor/profiles.rb new file mode 100644 index 0000000..f3129f6 --- /dev/null +++ b/src/lib/apparmor/profiles.rb @@ -0,0 +1,227 @@ +# Get the status of profiles loaded +# - enforced +# - complain +# Uses aa-status --json + +require "json" +require "open3" +Yast.import "UI" +Yast.import "Label" +Yast.import "Popup" + +module AppArmor + + class Profile + attr_reader :name, :status, :pid + + def initialize(name, status) + @name=name + @status=status + @pid = Array.new + end + + #Return/Set the name of the profile + def name(n="") + if n.length > 0 + @name = n + end + return @name + end + + #return the current status + def status(s="") + if s != "" + @status = s + end + return @status + end + + # Set to complain mode + def complain() + system("/usr/sbin/aa-complain #{@name}") + return self.status("complain") + end + + # Set to enforce mode + def enforce() + system("/usr/sbin/aa-enforce #{@name}") + return self.status("enforce") + end + + def addPid(p) + @pid.push(p) + end + + def pid + return @pid + end + + def toggle + if @status == "complain" + self.enforce + else + self.complain + end + end + + def to_s + @name + ", " + @status + ", " + @pid + end + + def to_array + a = Array.new + a.push(@name) + a.push(@status) + pstr = " " + # Convert PID array to a pretty string with commas + @pid.each do | p | + pstr = pstr + p.to_str + ", " + end + a.push(pstr) + return a + end + end + + class ProfileMap + def self.all(text) + jtext = JSON.parse(text) + h = jtext["profiles"] + entries = Hash.new + h.each do |name, status| + entries[name] = Profile.new(name, status) + end + h = jtext["processes"] + h.each do |name, pidmap| + pidmap.each do |p| + entries[name].addPid(p["pid"]) + end + end + return entries + end + end + + class Profiles + STATUS_CMD = "sudo /usr/sbin/aa-status --json" + attr_reader :raw, :prof + def initialize() + cmd = "#{STATUS_CMD}" + stdin, stdout, stderr, wait_thr = Open3.popen3(cmd) + @prof = ProfileMap.all(stdout.read) + end + + def remove(name) + e = @prof.delete(name) + # execute file deletion? + end + + def active() + # Select the ones which have pids + @prof.select { | name, pr | pr.pid.length > 0 } + end + + def all() + return @prof + end + + def toggle(name) + @prof[name].toggle + end + end + + class ProfilesDialog + include Yast::UIShortcuts + include Yast::I18n + include Yast::Logger + + def initialize + @profiles = Profiles.new + @active = true + end + + def run + return unless create_dialog + + begin + return event_loop + ensure + close_dialog + end + end + + private + def create_dialog + Yast::UI.OpenDialog( + Opt(:decorated, :defaultsize), + VBox( + #Header + Heading(_("Profile List")), + # Active profiles + Left( + CheckBox(Id(:active_only), Opt(:notify), _("Show Active only"), @active) + ), + VSpacing(0.4), + # Profile List + table, + VSpacing(0.3), + # Footer buttons + HBox( + HWeight(1, PushButton(Id(:changeMode), _("Change mode"))), + HStretch(), + HWeight(1, PushButton(Id(:finish), Yast::Label.FinishButton)) + ) + ) + ) + end + + def table + headers = Array[_("Name"), _("Mode"), _("PID")] + Table( + Id(:entries_table), + Opt(:keepSorting), + Header(*headers), + table_items + ) + end + + def table_items + if @active + profs = @profiles.active + else + profs = @profiles.all + end + arr = Array.new + profs.each do | n, pr | + arr.push(pr.to_array) + end + arr.map { |i| Item(*i) } + end + + def redraw_table + Yast::UI.ChangeWidget(Id(:entries_table), :Items, table_items) + end + + def event_loop + loop do + case Yast::UI.UserInput + when :active_only + @active = Yast::UI.QueryWidget(Id(:active_only), :Value) + redraw_table + when :cancel + break + when :changeMode + selectedItem = Yast::UI.QueryWidget(Id(:entries_table), :CurrentItem) + log.info "Toggling #{selectedItem}" + @profiles.toggle(selectedItem) + redraw_table + when :finish + break + end + end + end + + def close_dialog + Yast::UI.CloseDialog + 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