From: Goldwyn Rodrigues <[email protected]>

Handles the profiles using JSON output of aa-status. This replaces the earlier
way of handling profiles.

Signed-off-by: Goldwyn Rodrigues <[email protected]>
---
 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: [email protected]
To contact the owner, e-mail: [email protected]

Reply via email to