Hello community, here is the log from the commit of package yast2-firewall for openSUSE:Factory checked in at 2018-02-02 22:18:50 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/yast2-firewall (Old) and /work/SRC/openSUSE:Factory/.yast2-firewall.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "yast2-firewall" Fri Feb 2 22:18:50 2018 rev:57 rq:571969 version:4.0.10 Changes: -------- --- /work/SRC/openSUSE:Factory/yast2-firewall/yast2-firewall.changes 2018-01-28 00:36:53.216613953 +0100 +++ /work/SRC/openSUSE:Factory/.yast2-firewall.new/yast2-firewall.changes 2018-02-02 22:18:51.959444736 +0100 @@ -1,0 +2,9 @@ +Wed Jan 31 07:41:26 UTC 2018 - knut.anders...@suse.com + +- AutoYaST: (fate#323460) + * Try to import again during writing in case it was not completed + previously (ex: firewalld was not installed). + * Enable or disable firewalld depending on the profile +- 4.0.10 + +------------------------------------------------------------------- Old: ---- yast2-firewall-4.0.9.tar.bz2 New: ---- yast2-firewall-4.0.10.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ yast2-firewall.spec ++++++ --- /var/tmp/diff_new_pack.JZyaT1/_old 2018-02-02 22:18:52.591415232 +0100 +++ /var/tmp/diff_new_pack.JZyaT1/_new 2018-02-02 22:18:52.595415045 +0100 @@ -17,7 +17,7 @@ Name: yast2-firewall -Version: 4.0.9 +Version: 4.0.10 Release: 0 BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -27,13 +27,14 @@ BuildRequires: update-desktop-files BuildRequires: yast2-devtools >= 3.1.10 BuildRequires: yast2-testsuite -# IP::CheckNetwork -BuildRequires: yast2 >= 4.0.12 + +# Firewalld read? +BuildRequires: yast2 >= 4.0.45 BuildRequires: rubygem(%rb_default_ruby_abi:rspec) BuildRequires: rubygem(%rb_default_ruby_abi:yast-rake) -# FirewallD default zone & export support -Requires: yast2 >= 4.0.32 +# Firewalld read? +Requires: yast2 >= 4.0.45 # ButtonBox widget Conflicts: yast2-ycp-ui-bindings < 2.17.3 ++++++ yast2-firewall-4.0.9.tar.bz2 -> yast2-firewall-4.0.10.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-firewall-4.0.9/README.md new/yast2-firewall-4.0.10/README.md --- old/yast2-firewall-4.0.9/README.md 2018-01-19 10:28:54.000000000 +0100 +++ new/yast2-firewall-4.0.10/README.md 2018-02-02 11:16:34.000000000 +0100 @@ -5,12 +5,25 @@ [](https://travis-ci.org/yast/yast-firewall) [](https://ci.opensuse.org/view/Yast/job/yast-firewall-master/) -This repository contains basic set of shared libraries and so-called SCR agents -used for reading and writing configuration files and some even for executing -commands on the system. -Shared functionality is in another repository: -https://github.com/yast/yast-yast2/tree/master/library/network +Since the adoption of `firewalld` this repository contains just some useful +clients and libraries for installation and autoinstallation. + +The YaST Firewall GUI has been replaced by firewalld-config (a Gtk application) +and the text mode interface is not supported by now. + +An **API** to configure `Firewalld` is available in this repository: + +https://github.com/yast/yast-yast2/tree/master/library/network/src/lib/y2firewall + +## How to add / open services in YaST modules. + +For modules that just need to open a custom or predefined port in firewalld +the +[CWMFirewallInterfaces](https://github.com/yast/yast-yast2/tree/master/library/network/src/modules/CWMFirewallInterfaces.rb) +module has been adapted to work properly with the new **API.** + +For more documentation refer to this [link](doc/firewalld_services.md) ## Links ## diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-firewall-4.0.9/doc/firewalld_services.md new/yast2-firewall-4.0.10/doc/firewalld_services.md --- old/yast2-firewall-4.0.9/doc/firewalld_services.md 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-firewall-4.0.10/doc/firewalld_services.md 2018-02-02 11:16:34.000000000 +0100 @@ -0,0 +1,83 @@ + + +## Open / Modify Firewall Services + +A [firewalld service](http://www.firewalld.org/documentation/man-pages/firewalld.service.html) defines a set of ports, protocols and destination addresses simplyfying the process of allow/open them in a specific zone. + +In `YaST`, the [CWMFirewallInterfaces](https://github.com/yast/yast-yast2/tree/master/library/network/src/modules/CWMFirewallInterfaces.rb) module provides a widget definition for manipulating the enablement of services in zones through a selection of interfaces (each interface belongs to a **ZONE**). The module has been adapted to work properly with the new `firewalld API`. + + + +Being the implementation something like: + +```ruby + +Yast.import "CWMFirewallInterfaces" + +# You can still use "service:" prepend although it is recommended to remove +# it when adapting the module +settings = { "services" => ["service:cluster"], "display_details" => true } +CWMFirewallInterfaces.CreateOpenFirewallWidget(settings) +``` + +In most cases the only requirement will be to define the service in `firewalld` and probably it will be already +provided by the `firewalld` package. In summary the changes in code should look like: + +```ruby + +# Require the new firewalld library and drop any import of SuSEFirewall2 +require 'y2firewall/firewalld' + + ## This is not required but it is more elegant than using the complete call every time + def firewalld + Y2Firewall::Firewalld.instance + end + + # In your Module.Read method replace SuSEFirewalld.Read by firewalld.read + firewalld.read + # # In your Module.Write method replace SuSEFirewalld.Write by firewalld.read + firewalld.write + + +``` + +### Modify Service Ports Definition + +The service definitions shipped with firewalld can be modified. By default all the service definitions that came with firewalld are placed in `/usr/lib/firewalld/services` although if a service is modified then it is placed in `/etc/firewalld/services` allowing the admin to go back to the original definition if needed. + +SuSEFirewallServices has been dropped, so services configuration should be done through the new `Y2Firewall::Firewalld::Service` class. + +To modify the ports associated with a specific service, the class method `modify_ports` has been provided making the call as similar to the old one (`SetNeededPortsAndProtocols`) as possible. + +```ruby + + # SuSEFirewallServices.SetNeededPortsAndProtocols("service:cluster", { "tcp_ports" => tcp_ports }) + begin + Y2Firewall::Firewalld::Service.modify_ports(name: "cluster", tcp_ports: tcp_ports) + rescue Y2Firewall::Firewalld::Service::NotFound + y2error("Firewalld 'cluster' service is not available.") + end +``` + +To get the list of service ports we have to ask the service object itself. + +```ruby + # SuSEFirewallServices.GetNeededTCPPorts("service:cluster") + begin + fwd_cluster = firewalld.find_service("cluster") + tcp_ports = fwd_cluster.tcp_ports + rescue Y2Firewall::Firewalld::Service::NotFound + tcp_ports = [] + end + +``` + +## Important Note: + +If a `firewalld service` is not defined, then the `CWMFirewallInterfaces` widget will show a list of missing services suggesting to deploy them to be able to configure the firewall. + + + +New `services` can be created through the **API** or by a custom `XML` file although the preferred way is to define them in the `RPM` specification**. Please refer to this [link](https://en.opensuse.org/Firewalld/RPM_Packaging) for further information. + +Find a complete example including all the needed changes in this yast2-cluster [PR](https://github.com/yast/yast-cluster/pull/34) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-firewall-4.0.9/package/yast2-firewall.changes new/yast2-firewall-4.0.10/package/yast2-firewall.changes --- old/yast2-firewall-4.0.9/package/yast2-firewall.changes 2018-01-19 10:28:54.000000000 +0100 +++ new/yast2-firewall-4.0.10/package/yast2-firewall.changes 2018-02-02 11:16:34.000000000 +0100 @@ -1,4 +1,13 @@ ------------------------------------------------------------------- +Wed Jan 31 07:41:26 UTC 2018 - knut.anders...@suse.com + +- AutoYaST: (fate#323460) + * Try to import again during writing in case it was not completed + previously (ex: firewalld was not installed). + * Enable or disable firewalld depending on the profile +- 4.0.10 + +------------------------------------------------------------------- Fri Jan 19 08:44:25 UTC 2018 - knut.anders...@suse.com - AutoYaST: fixed default valur for log denied packets when using diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-firewall-4.0.9/package/yast2-firewall.spec new/yast2-firewall-4.0.10/package/yast2-firewall.spec --- old/yast2-firewall-4.0.9/package/yast2-firewall.spec 2018-01-19 10:28:54.000000000 +0100 +++ new/yast2-firewall-4.0.10/package/yast2-firewall.spec 2018-02-02 11:16:34.000000000 +0100 @@ -17,7 +17,7 @@ Name: yast2-firewall -Version: 4.0.9 +Version: 4.0.10 Release: 0 BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -27,13 +27,14 @@ License: GPL-2.0 BuildRequires: perl-XML-Writer update-desktop-files yast2-testsuite BuildRequires: yast2-devtools >= 3.1.10 -# IP::CheckNetwork -BuildRequires: yast2 >= 4.0.12 + +# Firewalld read? +BuildRequires: yast2 >= 4.0.45 BuildRequires: rubygem(%rb_default_ruby_abi:yast-rake) BuildRequires: rubygem(%rb_default_ruby_abi:rspec) -# FirewallD default zone & export support -Requires: yast2 >= 4.0.32 +# Firewalld read? +Requires: yast2 >= 4.0.45 # ButtonBox widget Conflicts: yast2-ycp-ui-bindings < 2.17.3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-firewall-4.0.9/src/lib/y2firewall/clients/auto.rb new/yast2-firewall-4.0.10/src/lib/y2firewall/clients/auto.rb --- old/yast2-firewall-4.0.9/src/lib/y2firewall/clients/auto.rb 2018-01-19 10:28:54.000000000 +0100 +++ new/yast2-firewall-4.0.10/src/lib/y2firewall/clients/auto.rb 2018-02-02 11:16:34.000000000 +0100 @@ -22,6 +22,7 @@ require "yast" require "y2firewall/firewalld" require "y2firewall/importer" +require "y2firewall/proposal_settings" require "installation/auto_client" module Y2Firewall @@ -30,28 +31,63 @@ # goes through the configuration and return the setting. # Does not do any changes to the configuration. class Auto < ::Installation::AutoClient + include Yast::Logger class << self + # @return [Boolean] whether the AutoYaST configuration has been + # modified or not attr_accessor :changed + # @return [Boolean] whether the AutoYaST configuration was imported + # successfully or not + attr_accessor :imported + # @return [Boolean] whether the firewalld service has to be enabled + # after writing the configuration + attr_accessor :enable + # @return [Boolean] whether the firewalld service has to be started + # after writing the configuration + attr_accessor :start + # @return [Hash] + attr_accessor :profile end + # Constructor def initialize textdomain "firewall" end + # Configuration summary + # + # @return [String] def summary + return "" if !firewalld.installed? + firewalld.api.list_all_zones.join("\n") end + # Import the firewall configuration + # + # @param profile [Hash] firewall profile section to be imported + # @return [Boolean] def import(profile) - firewalld.read + self.class.profile = profile + return false unless read + # Obtains the default from the control file (settings) if not present. + enable if profile.fetch("enable_firewall", settings.enable_firewall) + start if profile.fetch("start_firewall", false) importer.import(profile) + imported end + # Export the current firewalld configuration + # + # @return [Hash] with the current firewalld configuration def export firewalld.export end + # Reset the current firewalld configuration. + # + # @return [Boolean] def reset importer.import({}) end @@ -62,16 +98,33 @@ :next end + # Write the imported configuration to firewalld. If for some reason the + # configuration was not imported from the profile, it tries to import + # it again. def write + return false if !firewalld.installed? + import(self.class.profile) unless imported? + return false unless imported? + firewalld.write + activate_service end + # Read the currnet firewalld configuration def read - firewalld.read if firewalld.installed? + return false if !firewalld.installed? + return true if firewalld.read? + + firewalld.read end + # A map with the packages that needs to be installed or removed for + # configuring firewalld properly + # + # @return packages [Hash{String => Array<String>} ] of packages to be + # installed or removed def packages - ["firewalld"] + { "install" => ["firewalld"], "remove" => [] } end def modified @@ -79,17 +132,71 @@ end def modified? - self.class.changed + !!self.class.changed end private + # Depending on the profile it activates or deactivates the firewalld + # service + def activate_service + enable? ? firewalld.enable! : firewalld.disable! + start? ? firewalld.start : firewalld.stop + end + + # Return a firewall importer + # + # @return [Y2Firewall::Importer] def importer - @importer ||= ::Y2Firewall::Importer.new + @importer ||= Importer.new end + # Return a firewalld singleton instance + # + # @return [Y2Firewall::Firewalld] singleton instance def firewalld - ::Y2Firewall::Firewalld.instance + Firewalld.instance + end + + # @return [Y2Firewall::ProposalSettings] + def settings + ProposalSettings.instance + end + + # Set that the firewall has to be enabled when writing + def enable + self.class.enable = true + end + + # Whether the firewalld service has to be enable or disable when writing + # + # @return [Boolean] true if has to be enabled; false otherwise + def enable? + !!self.class.enable + end + + # Set that the firewall has to be started when writing + def start + self.class.start = true + end + + # Whether the firewalld service has to be started or stopped when writing + # + # @return [Boolean] true if has to be started; false otherwise + def start? + !!self.class.start + end + + # Set that the firewalld configuration has been completely imported + def imported + self.class.imported = true + end + + # Whether the firewalld configuration has been already imported or not + # + # @return [Boolean] true if has been imported; false otherwise + def imported? + !!self.class.imported end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-firewall-4.0.9/src/lib/y2firewall/clients/installation_finish.rb new/yast2-firewall-4.0.10/src/lib/y2firewall/clients/installation_finish.rb --- old/yast2-firewall-4.0.9/src/lib/y2firewall/clients/installation_finish.rb 2018-01-19 10:28:54.000000000 +0100 +++ new/yast2-firewall-4.0.10/src/lib/y2firewall/clients/installation_finish.rb 2018-02-02 11:16:34.000000000 +0100 @@ -47,7 +47,7 @@ end def modes - [:installation, :autoinst] + [:installation] end def write diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-firewall-4.0.9/src/lib/y2firewall/importer.rb new/yast2-firewall-4.0.10/src/lib/y2firewall/importer.rb --- old/yast2-firewall-4.0.9/src/lib/y2firewall/importer.rb 2018-01-19 10:28:54.000000000 +0100 +++ new/yast2-firewall-4.0.10/src/lib/y2firewall/importer.rb 2018-02-02 11:16:34.000000000 +0100 @@ -28,6 +28,7 @@ # This class is responsible for importing firewalld AutoYaST configuration # supporting the new firewalld schema but also the SuSEFirewall one. class Importer + include Yast::Logger # Import the given configuration # # @param [Hash] AutoYaST profile firewall's section diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-firewall-4.0.9/src/lib/y2firewall/importer_strategies/suse_firewall.rb new/yast2-firewall-4.0.10/src/lib/y2firewall/importer_strategies/suse_firewall.rb --- old/yast2-firewall-4.0.9/src/lib/y2firewall/importer_strategies/suse_firewall.rb 2018-01-19 10:28:54.000000000 +0100 +++ new/yast2-firewall-4.0.10/src/lib/y2firewall/importer_strategies/suse_firewall.rb 2018-02-02 11:16:34.000000000 +0100 @@ -26,6 +26,7 @@ # This class is reponsible of parsing SuSEFirewall2 firewalld profile's # section configuring the Y2Firewall::Firewalld instance according to it. class SuseFirewall + include Yast::Logger # @return [Hash] AutoYaST profile firewall's section attr_accessor :profile @@ -64,11 +65,14 @@ # It processes the profile configuring the firewalld zones that match # better with the SuSEFirewall2 ones. def import - return true if profile.empty? + if profile.empty? + log.info "The profile is empty, there is nothing to import" + return true + end zones.each { |z| process_zone(z) } if ipsec_trust_zone zone = firewalld.find_zone(zone.equivalent(ipsec_trust_zone)) - zone.services << "ipsec" + (zone.services << "ipsec") if zone end firewalld.log_denied_packets = log_denied_packets true @@ -81,7 +85,12 @@ # object. # @param name [String] SuSEFirewall2 zone name def process_zone(name) + log.info "Processing zone #{name}" zone = firewalld.find_zone(zone_equivalent(name)) + if !zone + log.error "There is no zone for #{name}" + return + end if interfaces(name) zone.interfaces = interfaces(name) @@ -164,7 +173,7 @@ # configured def tcp_ports(zone) ports = profile["FW_SERVICES_#{zone}_TCP"] - ports ? ports.split(" ").map { |p| "#{p}/tcp" } : nil + ports ? ports.split(" ").map { |p| "#{p.sub(":", "-")}/tcp" } : nil end # Obtain the UDP ports for the given SuSEFIrewall2 zone name from the @@ -175,7 +184,7 @@ # configured def udp_ports(zone) ports = profile["FW_SERVICES_#{zone}_UDP"] - ports ? ports.split(" ").map { |p| "#{p}/udp" } : nil + ports ? ports.split(" ").map { |p| "#{p.sub(":", "-")}/udp" } : nil end # Obtain the RPC ports for the given SuSEFIrewall2 zone name from the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-firewall-4.0.9/test/lib/y2firewall/clients/auto_test.rb new/yast2-firewall-4.0.10/test/lib/y2firewall/clients/auto_test.rb --- old/yast2-firewall-4.0.9/test/lib/y2firewall/clients/auto_test.rb 2018-01-19 10:28:54.000000000 +0100 +++ new/yast2-firewall-4.0.10/test/lib/y2firewall/clients/auto_test.rb 2018-02-02 11:16:34.000000000 +0100 @@ -27,7 +27,9 @@ let(:importer) { double("Y2Firewall::Importer", import: true) } before do + subject.class.imported = false allow(firewalld).to receive(:read) + allow(firewalld).to receive(:installed?).and_return(true) allow(subject).to receive(:importer).and_return(importer) end @@ -49,7 +51,9 @@ end describe "#import" do - let(:arguments) { { "FW_MASQUERADE" => "yes" } } + let(:arguments) do + { "FW_MASQUERADE" => "yes", "enable_firewall" => false, "start_firewall" => false } + end it "reads the current firewalld configuration" do expect(firewalld).to receive(:read) @@ -57,14 +61,38 @@ subject.import(arguments) end - it "pass its arguments to the firewalld importer" do - expect(importer).to receive(:import).with(arguments) - - subject.import(arguments) - end - - it "returns true if import success" do - expect(subject.import(arguments)).to eq(true) + context "when the current configuration was read correctly" do + before do + allow(firewalld).to receive(:read).and_return(true) + end + + it "pass its arguments to the firewalld importer" do + expect(importer).to receive(:import).with(arguments) + + subject.import(arguments) + end + + it "returns true if import success" do + expect(subject.import(arguments)).to eq(true) + end + + it "marks the importation as done" do + subject.import(arguments) + expect(subject.class.imported).to eq(true) + end + end + + context "when the current configuration was not read" do + it "returns false" do + expect(firewalld).to receive(:read).and_return(false) + expect(subject.import(arguments)).to eq(false) + end + + it "does not mark the importation as done or completed" do + expect(firewalld).to receive(:read).and_return(false) + subject.import(arguments) + expect(subject.class.imported).to eq(false) + end end end @@ -86,4 +114,39 @@ subject.reset end end + + describe "#write" do + let(:arguments) do + { "FW_MASQUERADE" => "yes", "enable_firewall" => false, "start_firewall" => false } + end + + it "returns false if firewalld is not installed" do + expect(firewalld).to receive(:installed?).and_return(false) + + expect(subject.write).to eq(false) + end + + it "tries to import again the profile if it was not imported" do + allow(subject.class).to receive(:profile).and_return(arguments) + expect(subject).to receive(:import).with(arguments).and_return(false) + + subject.write + end + + it "writes the imported configuration" do + allow(subject.class).to receive(:imported).and_return(true) + allow(subject).to receive(:activate_service) + expect(firewalld).to receive(:write) + + subject.write + end + + it "activates or deactives the firewalld service based on the profile" do + allow(subject.class).to receive(:imported).and_return(true) + expect(firewalld).to receive(:write) + expect(subject).to receive(:activate_service) + + subject.write + end + end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-firewall-4.0.9/test/lib/y2firewall/clients/installation_finish_test.rb new/yast2-firewall-4.0.10/test/lib/y2firewall/clients/installation_finish_test.rb --- old/yast2-firewall-4.0.9/test/lib/y2firewall/clients/installation_finish_test.rb 2018-01-19 10:28:54.000000000 +0100 +++ new/yast2-firewall-4.0.10/test/lib/y2firewall/clients/installation_finish_test.rb 2018-02-02 11:16:34.000000000 +0100 @@ -14,7 +14,7 @@ describe "#modes" do it "runs on installation and autoinstallation" do - expect(subject.modes).to eq([:installation, :autoinst]) + expect(subject.modes).to eq([:installation]) end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-firewall-4.0.9/test/lib/y2firewall/importer_strategies/suse_firewall.rb new/yast2-firewall-4.0.10/test/lib/y2firewall/importer_strategies/suse_firewall.rb --- old/yast2-firewall-4.0.9/test/lib/y2firewall/importer_strategies/suse_firewall.rb 2018-01-19 10:28:54.000000000 +0100 +++ new/yast2-firewall-4.0.10/test/lib/y2firewall/importer_strategies/suse_firewall.rb 2018-02-02 11:16:34.000000000 +0100 @@ -42,7 +42,8 @@ "FW_DEV_INT" => "eth1", "FW_DEV_DMZ" => "eth2 any", "FW_CONFIGURATIONS_EXT" => "dhcp-server sshd netbios-server vnc-server", - "FW_SERVICES_EXT_TCP" => "80 443", + "FW_SERVICES_EXT_TCP" => "80 443 8080:8084", + "FW_SERVICES_EXT_UDP" => "53", "FW_SERVICES_EXT_IP" => "esp", "FW_MASQUERADE" => masquerade } @@ -85,6 +86,7 @@ expect(public_zone.interfaces).to eq(["eth0"]) expect(public_zone.services).to eq(["dhcp", "ssh", "samba", "vnc-server"]) + expect(public_zone.ports).to eq(["80/tcp", "443/tcp", "8080-8084/tcp", "53/udp"]) expect(public_zone.protocols).to eq(["esp"]) end end