]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/commitdiff
IDS: Redesign backend for used provider rulesfiles.
authorStefan Schantl <stefan.schantl@ipfire.org>
Thu, 1 Apr 2021 09:39:57 +0000 (11:39 +0200)
committerStefan Schantl <stefan.schantl@ipfire.org>
Sun, 19 Dec 2021 12:23:32 +0000 (13:23 +0100)
The selected rulesfiles of a provider now will be written to an own
provider exclusive yaml file, which will be included dynamically when
the provider is enabled or not.

This allows very easy handling to enable or disable a provider, in this
case the file which keeps the enabled providers rulesets only needs to
be included in the main file or even not.

Signed-off-by: Stefan Schantl <stefan.schantl@ipfire.org>
config/cfgroot/ids-functions.pl
config/suricata/suricata.yaml
html/cgi-bin/ids.cgi

index ed9bb203bae432e2ed27f037e3c9a2594af94f7a..245a267bf264ab0ef09d8b11c0852509ee01130d 100644 (file)
@@ -27,12 +27,15 @@ package IDS;
 
 require '/var/ipfire/general-functions.pl';
 require "${General::swroot}/network-functions.pl";
-require "${General::swroot}/suricata/ruleset-sources";
+require "${General::swroot}/suricata/ruleset-sources-new";
 
 # Location where all config and settings files are stored.
 our $settingsdir = "${General::swroot}/suricata";
 
-# File where the used rulefiles are stored.
+# File where the main file for providers ruleset inclusion exists.
+our $suricata_used_providers_file = "$settingsdir/suricata-used-providers.yaml";
+
+# DEPRECATED - File where the used rulefiles are stored.
 our $used_rulefiles_file = "$settingsdir/suricata-used-rulefiles.yaml";
 
 # File where the addresses of the homenet are stored.
@@ -138,7 +141,7 @@ sub check_and_create_filelayout() {
        unless (-f "$enabled_sids_file") { &create_empty_file($enabled_sids_file); }
        unless (-f "$disabled_sids_file") { &create_empty_file($disabled_sids_file); }
        unless (-f "$modify_sids_file") { &create_empty_file($modify_sids_file); }
-       unless (-f "$used_rulefiles_file") { &create_empty_file($used_rulefiles_file); }
+       unless (-f "$suricata_used_providers_file") { &create_empty_file($suricata_used_providers_file); }
        unless (-f "$ids_settings_file") { &create_empty_file($ids_settings_file); }
        unless (-f "$providers_settings_file") { &create_empty_file($providers_settings_file); }
        unless (-f "$ignored_file") { &create_empty_file($ignored_file); }
@@ -1226,13 +1229,18 @@ sub generate_http_ports_file() {
 }
 
 #
-## Function to generate and write the file for used rulefiles.
+## Function to generate and write the file for used rulefiles file for a given provider.
+##
+## The function requires as first argument a provider handle, and as second an array with files.
 #
-sub write_used_rulefiles_file(@) {
-       my @files = @_;
+sub write_used_provider_rulefiles_file($@) {
+       my ($provider, @files) = @_;
+
+       # Get the path and file for the provider specific used rulefiles file.
+       my $used_provider_rulesfile_file = &get_used_provider_rulesfile_file($provider);
 
        # Open file for used rulefiles.
-       open (FILE, ">$used_rulefiles_file") or die "Could not write to $used_rulefiles_file. $!\n";
+       open (FILE, ">$used_provider_rulesfile_file") or die "Could not write to $used_provider_rulesfile_file. $!\n";
 
        # Write yaml header to the file.
        print FILE "%YAML 1.1\n";
@@ -1241,9 +1249,6 @@ sub write_used_rulefiles_file(@) {
        # Write header to file.
        print FILE "#Autogenerated file. Any custom changes will be overwritten!\n";
 
-       # Allways use the whitelist.
-       print FILE " - whitelist.rules\n";
-
        # Loop through the array of given files.
        foreach my $file (@files) {
                # Check if the given filename exists and write it to the file of used rulefiles.
@@ -1256,6 +1261,53 @@ sub write_used_rulefiles_file(@) {
        close(FILE);
 }
 
+#
+## Function to write the main file for provider rulesfiles inclusions.
+##
+## This function requires an array of provider handles.
+#
+sub write_main_used_rulefiles_file (@) {
+       my (@providers) = @_;
+
+       # Open file for used rulefils inclusion.
+       open (FILE, ">", "$suricata_used_providers_file") or die "Could not write to $suricata_used_providers_file. $!\n";
+
+       # Write yaml header to the file.
+       print FILE "%YAML 1.1\n";
+       print FILE "---\n\n";
+
+       # Write header to file.
+       print FILE "#Autogenerated file. Any custom changes will be overwritten!\n";
+
+       # Loop through the list of given providers.
+       foreach my $provider (@providers) {
+               # Call function to get the providers used rulefiles file.
+               my $filename = &get_used_provider_rulesfile_file($provider);
+
+               # Print the provider to the file.
+               print FILE "include\: $filename\n";
+       }
+
+       # XXX - whitelist.rules is not allowed directly, needs to be in a yaml file which has to be included.
+       # Always use the whitelist file.
+       #print FILE "\n - whitelist.rules\n";
+
+       # Close the filehandle after writing.
+       close(FILE);
+}
+
+#
+## Tiny function to generate the full path and name for the used_provider_rulesfile file of a given provider.
+#
+sub get_used_provider_rulesfile_file ($) {
+       my ($provider) = @_;
+
+       my $filename = "$settingsdir/suricata\-$provider\-used\-rulefiles.yaml";
+
+       # Return the gernerated file.
+       return $filename;
+}
+
 #
 ## Function to generate and write the file for modify the ruleset.
 #
@@ -1509,16 +1561,21 @@ sub get_red_address() {
 }
 
 #
-## Function to get all used rulesfiles files.
+## Function to get the used rules files of a given provider.
 #
-sub get_used_rulesfiles() {
+sub read_used_provider_rulesfiles($) {
+       my ($provider) = @_;
+
        # Array to store the used rulefiles.
        my @used_rulesfiles = ();
 
+       # Get the used rulesefile file for the provider.
+       my $rulesfile_file = &get_used_provider_rulesfile_file($provider);
+
        # Check if the used rulesfile is empty.
-       unless (-z $used_rulefiles_file) {
+       unless (-z $rulesfile_file) {
                # Open the file or used rulefiles and read-in content.
-               open(FILE, $used_rulefiles_file) or die "Could not open $used_rulefiles_file. $!\n";
+               open(FILE, $rulesfile_file) or die "Could not open $rulesfile_file. $!\n";
 
                while (<FILE>) {
                        # Assign the current line to a nice variable.
index b4a188d4045287b3e46ebc7eda6c7ef6a2174101..84f50f54ecb28f1d93b770301c2be1649513c301 100644 (file)
@@ -46,8 +46,8 @@ vars:
 ##
 default-rule-path: /var/lib/suricata
 rule-files:
-    # Include enabled ruleset files from external file
-    include: /var/ipfire/suricata/suricata-used-rulefiles.yaml
+    # Include enabled ruleset files from external file.
+    include: /var/ipfire/suricata/suricata-used-providers.yaml
 
     # Include default rules.
     include: /var/ipfire/suricata/suricata-default-rules.yaml
index a1be76b792e050b09c05fd7fa841e8319ab7b911..908ad9c287a894213bd6901a66389c6881652220 100644 (file)
@@ -254,6 +254,10 @@ if (-e $IDS::storederrorfile) {
 if ($cgiparams{'RULESET'}) {
        ## Grab all available rules and store them in the idsrules hash.
        #
+
+       # Get enabled providers.
+       my @enabled_providers = &IDS::get_enabled_providers();
+
        # Open rules directory and do a directory listing.
        opendir(DIR, $IDS::rulespath) or die $!;
                # Loop through the direcory.
@@ -274,6 +278,15 @@ if ($cgiparams{'RULESET'}) {
                        # Skip whitelist rules file.
                        next if( $file eq "whitelist.rules");
 
+                       # Splitt vendor from filename.
+                       my @filename_parts = split(/-/, $file);
+
+                       # Assign vendor name for easy processing.
+                       my $vendor = @filename_parts[0];
+
+                       # Skip rulefile if the provider is disabled.
+                       next unless ($vendor ~~ @enabled_providers);
+
                        # Call subfunction to read-in rulefile and add rules to
                        # the idsrules hash.
                        &readrulesfile("$file");
@@ -281,17 +294,20 @@ if ($cgiparams{'RULESET'}) {
 
        closedir(DIR);
 
-       # Gather used rulefiles.
-       my @used_rulesfiles = &IDS::get_used_rulesfiles();
-
-       # Loop through the array of used rulesfiles.
-       foreach my $rulesfile (@used_rulesfiles) {
-               # Check if the current rulefile exists in the %idsrules hash.
-               # If not, the file probably does not exist anymore or contains
-               # no rules.
-               if($idsrules{$rulefile}) {
-                       # Add the rulefile state to the %idsrules hash.
-                       $idsrules{$rulefile}{'Rulefile'}{'State'} = "on";
+       # Loop through the array of used providers.
+       foreach my $provider (@enabled_providers) {
+               # Gather used rulefiles.
+               my @used_rulesfiles = &IDS::read_used_provider_rulesfiles($provider);
+
+               # Loop through the array of used rulesfiles.
+               foreach my $rulefile (@used_rulesfiles) {
+                       # Check if the current rulefile exists in the %idsrules hash.
+                       # If not, the file probably does not exist anymore or contains
+                       # no rules.
+                       if($idsrules{$rulefile}) {
+                               # Add the rulefile state to the %idsrules hash.
+                               $idsrules{$rulefile}{'Rulefile'}{'State'} = "on";
+                       }
                }
        }
 }
@@ -479,8 +495,40 @@ if ($cgiparams{'RULESET'} eq $Lang::tr{'save'}) {
        # Close file for disabled_sids after writing.
        close(DISABLED_FILE);
 
+       # Handle enabled / disabled rulefiles.
+       #
+       # Get enabled providers.
+       my @enabled_providers = &IDS::get_enabled_providers();
+
+       # Loop through the array of enabled providers.
+       foreach my $provider(@enabled_providers) {
+               # Array to store the rulefiles which belong to the current processed provider.
+               my @provider_rulefiles = ();
+
+               # Loop through the array of enabled rulefiles.
+               foreach my $rulesfile (@enabled_rulefiles) {
+                       # Split the rulefile name.
+                       my @filename_parts = split(/-/, "$rulesfile");
+
+                       # Assign vendor name for easy processings.
+                       my $vendor = @filename_parts[0];
+
+                       # Check if the rulesvendor is our current processed enabled provider.
+                       if ("$vendor" eq "$provider") {
+                               # Add the rulesfile to the array of provider rulesfiles.
+                               push(@provider_rulefiles, $rulesfile);
+                       }
+
+                       # Check if any rulesfiles have been found for this provider.
+                       if (@provider_rulefiles) {
+                               # Call function and write the providers used rulesfile file.
+                               &IDS::write_used_provider_rulefiles_file($provider, @provider_rulefiles);
+                       }
+               }
+       }
+
        # Call function to generate and write the used rulefiles file.
-       &IDS::write_used_rulefiles_file(@enabled_rulefiles);
+       &IDS::write_main_used_rulefiles_file(@enabled_providers);
 
        # Lock the webpage and print message.
        &working_notice("$Lang::tr{'ids apply ruleset changes'}");
@@ -779,6 +827,10 @@ if ($cgiparams{'RULESET'} eq $Lang::tr{'save'}) {
                        # Cleanup temporary directory.
                        &IDS::cleanup_tmp_directory();
 
+                       # Create new empty file for used rulefiles
+                       # for this provider.
+                       &IDS::write_used_provider_rulefiles_file($provider);
+
                        # Perform a reload of the page.
                        &reload();
                }