App package needs update-fortinet-FortiOS

warn
fortios
fortinet
App package needs update-fortinet-FortiOS
0

#1

App package needs update-fortinet-FortiOS

Vendor: fortinet

OS: FortiOS

Description:
indeni will trigger an issue when app package has not been updated.

Remediation Steps:
Renew any app packages that need to be updated.
||
|1. Login via ssh to the Fortinet firewall and execute the FortiOS “get system fortiguard-service status” command to list current update package versions and license expiry date and status.
|2. Login via ssh to the Fortinet firewall and execute the FortiOS “diag autoupdate versions” and “diag autoupdate status” commands to get more details about the update policy and last update of the UTM services.
|3. Login via https to the Fortinet firewall and go to the menu System > Dashboard > Status to locate the License Information widget. All subscribed services should have a green checkmark, indicating that connections are successful. A gray X indicates that the FortiGate unit cannot connect to the FortiGuard network, or that the FortiGate unit is not registered. A red X indicates that the FortiGate unit was able to connect but that a subscription has expired or has not been activated.
|4. Verify that the Fortigate has internet access and then login via https to the Fortinet firewall to view the FortiGuard connection status by going to System > Config > FortiGuard menu. Select “Update Now” under AV & IPS Download Options to force a sync. In case of an update problem with the Web Filtering and Email Filtering expand the “Web Filtering and Email Filtering Options” and Change Port Selection to use an Alternate Port (8888) and press “Test Availability”. Wait a few minutes and verify the license health status.
|5. If the registration does not appear after changing to Alternate Port mentioned to the above step, try pinging the FortiGuard services URL using command “exec ping service.fortiguard.net”. If that resolves to an IP then type the following commands:
| - diag debug app update -1
| - diag debug en
| - exec update-now
|If it does not resolve to an IP then this is a DNS issue.
|Note: At the end disable the debug.
|6. If you are using multiple VDOMS on the FortiGate, make sure that you have an Internet-facing VDOM set as the management vdom.
|7. For more information about licensing review the next online article “Setting up FortiGuard services” : http://cookbook.fortinet.com/setting-fortiguard-services-54/
|8. Contact Fortinet Technical support at https://support.fortinet.com/ for further assistance.

How does this work?
This script logs into the Fortigate using SSH and retrieves the Fortiguard Definition or last update by using the output of the FortiOS command “get system fortiguard-service status”. The “get system fortiguard-service status” FortiOS command allows to view detailed information about the installed versions, expiration date and last update of the installed fortiguard licenses such as AV, IPS and Application control.

Why is this important?
This metric is used to identify the last update of the FortiGuard Service Engine or Definition. More information can be found at: https://docs.fortinet.com/uploaded/files/2810/fortigate-security-profiles-guide-540.pdf

Without Indeni how would you find this?
An adminisrator would need to log into the Fortinet firewall and manually check the expiration and last update of each Fortiguard license. A log message can notify the administrator about the license expiration date. This information can also be provided via the FortiManager and the FortiAnalyzer.

fortios-get-system-fortiguard-service-status

#! META
name: fortios-get-system-fortiguard-service-status
description: Fortinet firewall FortiGuard license expiration and update status
type: monitoring
monitoring_interval: 59 minutes
requires:
    vendor: fortinet
    os.name: FortiOS
    product: firewall
    vdom_enabled: false
    vdom_root: true

# --------------------------------------------------------------------------------------------------
# The script publish the following metrics
#
#  Metric with Expiry Date
#  [license-expiration]                              [date]
#   1. tag-name:[AntiVirus Engine]
#   2. tag-name:[AntiVirus Definitions]
#   3. tag-name:[Flow-based AntiVirus Definitions]
#   4. tag-name:[IPS Attack Definitions]
#   5. tag-name:[IPS Malicious URL Database]
#   6. tag-name:[Botnet Definitions]
#   7. tag-name:[IPS/FlowAV Engine]
#   8. tag-name:[Application Definitions]
#   9. tag-name:[Industrial Attack Definitions]
#
#   Metric with Update Date
#  [package-last-update]                              [date]
#   1. tag-name:[Last Update of the AntiVirus Engine]
#   2. tag-name:[Last Update of the AntiVirus Definitions]
#   3. tag-name:[Last Update of the IPS Attack Definitions]
#   4. tag-name:[Last Update of the IPS/Flow AntiVirus Engine]
#   5. tag-name:[Last Update of the Application Definitions]
#
# --------------------------------------------------------------------------------------------------


#! COMMENTS
license-expiration:
    why: |
       This metric is used to identify the expiration date and last update of the FortiGuard licenses. More information
       can be found at: https://docs.fortinet.com/uploaded/files/2810/fortigate-security-profiles-guide-540.pdf
    how: |
        This script logs into the Fortigate using SSH and retrieves the Fortiguard license expiration date by using the
        output of the FortiOS command "get system fortiguard-service status". The "get system fortiguard-service
        status" FortiOS command allows to view detailed information about the installed versions, expiration date and
        last update of the installed fortiguard licenses such as AV, IPS and Application control.
    without-indeni: |
         An adminisrator would need to log into the Fortinet firewall and manually check the expiration and last update
         of each Fortiguard license. A log message can notify the administrator about the license expiration date. This
         information can also be provided via the FortiManager and the FortiAnalyzer.
    can-with-snmp: false
    can-with-syslog: true

package-last-update:
    why: |
        This metric is used to identify the last update of the FortiGuard Service Engine or Definition. More
        information can be found at:
        https://docs.fortinet.com/uploaded/files/2810/fortigate-security-profiles-guide-540.pdf
    how: |
        This script logs into the Fortigate using SSH and retrieves the Fortiguard Definition or last update by using
        the output of the FortiOS command "get system fortiguard-service status". The
        "get system fortiguard-service status" FortiOS command allows to view detailed information about the installed
        versions, expiration date and last update of the installed fortiguard licenses such as AV, IPS and Application
        control.
    without-indeni: |
         An adminisrator would need to log into the Fortinet firewall and manually check the expiration and last update
         of each Fortiguard license. A log message can notify the administrator about the license expiration date. This
         information can also be provided via the FortiManager and the FortiAnalyzer.
    can-with-snmp: false
    can-with-syslog: true


#! REMOTE::SSH
get system fortiguard-service status

#! PARSER::AWK

#-----------------------------------------------------------------------
# Helper function.
# Convert date in format '2016-11-16' , '15:45:00' to epoch seconds
# Special cases:
#   In case of 'n/a' return 'n/a'
#   In case of invalid format return ''
#-----------------------------------------------------------------------
function getInEpoch(dateString, timeString) {

    # Handle a special case of 'n/a' input
    if (trim(timeString) == "n/a")
        return "n/a"

    # Read date in format '2016-11-16'
    length1 = split(dateString, date_array, "-")

    # Read time in format '15:45:00'
    length2 = split(timeString, time_array, ":")

    # Check size of the arrays (if the length not 3 then return an empty string, failed to parsed input values)
    if (length1 != 3 || length2 != 3)
        return ""

    epoch_time = datetime(date_array[1], date_array[2], date_array[3], time_array[1], time_array[2], time_array[3])
    return epoch_time
}

#-----------------------------------------------------------------------
# Helper function.
# Publish date metric, if the date has a valid positive value.
#-----------------------------------------------------------------------
function publishDateMetricIfExist(metricName, tagName, metricCategory, dateToPublish){
    # Check first if metric has a value and the value is number
    if (dateToPublish > 0) {
        tags["name"] = tagName
        writeDoubleMetricWithLiveConfig(metricName, tags, "gauge", 300, dateToPublish , metricCategory, "date", "name")
    }
}


#-----------------------------------------------------------------------
# Helper function.
# Retrieve "updated-date" (third column) from a line like:
#[AV Engine           5.247  2017-05-04 14:26:00  manual    2018-01-01 17:00:00]
# After removing the first column 'stringRemovePart'.
# In the above example the stringRemovePart would be 'AV Engine'
#-----------------------------------------------------------------------
function getLastUpdateEpoch(stringLine, stringRemovePart){

    #AV Engine           5.247  2017-05-04 14:26:00  manual    2018-01-01 17:00:00
    # Remove the part ('AV Engine') and trim the sentence
    stringLineWithDate = trim( substr(stringLine, length(stringRemovePart)+1) )

    # Replace the 2 spaces or more with a single space
    gsub(/[ ]{2,}/, " ", stringLineWithDate)

    # Split the line in an array using as separator the single ' '
    split(stringLineWithDate, stringLineWithDateArray, /\s/)

    # Use the parts 2 and 3 of the array. part-2 is '2017-05-04' and part-3 is '14:26:00'
    return getInEpoch(stringLineWithDateArray[2], stringLineWithDateArray[3])
}

#AV Engine           5.247  2017-05-04 14:26:00  manual    2018-01-01 17:00:00
/^AV Engine /{

    # Generate in epoch the expiry-time (last-column) the 2016-11-16 & 15:45:00 (Expiration Date of AV Engine)
    date_expire_epoch = getInEpoch($(NF-1), $NF)
    publishDateMetricIfExist("license-expiration", "AntiVirus Engine", "Licenses Expire date", date_expire_epoch)

    # Generate in epoch the update-time (third-column) 2016-11-16 & 15:45:00 (Update Date of AV Engine)
    date_update_epoch = getLastUpdateEpoch($0, "AV Engine")
    publishDateMetricIfExist("package-last-update", "Last Update of the AntiVirus Engine", "FortiGuard Services Last Update", date_update_epoch)

}

#Virus Definitions   52.696  2017-10-31 03:31:17  manual    2018-01-01 17:00:00
/^Virus Definitions /{

    # Generate in epoch the expiry-time (last-column) the 2016-11-16 & 15:45:00 (Expiration Date of Virus Definitions)
    date_expire_epoch = getInEpoch($(NF-1), $NF)
    publishDateMetricIfExist("license-expiration", "AntiVirus Definitions", "Licenses Expire date", date_expire_epoch)

    # Generate in epoch the update-time (third-column) 2016-11-16 & 15:45:00 (Update Date of Virus Definitions)
    date_update_epoch = getLastUpdateEpoch($0, "Virus Definitions")
    publishDateMetricIfExist("package-last-update", "Last Update of the AntiVirus Definitions", "FortiGuard Services Last Update", date_update_epoch)

}

#Flow-based Virus Definitions  52.696  2017-10-31 03:31:17  manual    2018-01-01 17:00:00
/^Flow-based Virus Definitions /{

    # Generate in epoch the expiry-time (last-column) the 2016-11-16 & 15:45:00 (Expiration Date of Flow-based Virus Definitions)
    date_expire_epoch = getInEpoch($(NF-1), $NF)
    publishDateMetricIfExist("license-expiration", "Flow-based AntiVirus Definitions", "Licenses Expire date", date_expire_epoch)

}

#Attack Definitions  12.255  2017-10-31 03:31:17  manual    2018-01-01 17:00:00
/^Attack Definitions /{

    # Generate in epoch the expiry-time (last-column) the 2016-11-16 & 15:45:00 (Expiration Date of Attack Definitions)
    date_expire_epoch = getInEpoch($(NF-1), $NF)
    publishDateMetricIfExist("license-expiration", "IPS Attack Definitions", "Licenses Expire date", date_expire_epoch)

    # Generate in epoch the update-time (third-column) 2016-11-16 & 15:45:00 (Update Date of Attack Definitions)
    date_update_epoch = getLastUpdateEpoch($0, "Attack Definitions")
    publishDateMetricIfExist("package-last-update", "Last Update of the IPS Attack Definitions", "FortiGuard Services Last Update", date_update_epoch)

}

#IPS Malicious URL Database  1.001  2015-01-01 01:01:00  manual    n/a
/^IPS Malicious URL Database /{

    # Generate in epoch the expiry-time (last-column) the 2016-11-16 & 15:45:00 (Expiration Date of IPS Malicious URL Database)
    date_expire_epoch = getInEpoch($(NF-1), $NF)
    publishDateMetricIfExist("license-expiration", "Expiration Date of IPS Malicious URL Database", "Licenses Expire date", date_expire_epoch)


}

#Botnet Definitions  1.000  2012-05-28 22:51:00  manual    n/a
/^Botnet Definitions /{

    # Generate in epoch the expiry-time (last-column) the 2016-11-16 & 15:45:00 (Expiration Date of Botnet Definitions)
    date_expire_epoch = getInEpoch($(NF-1), $NF)
    publishDateMetricIfExist("license-expiration", "Botnet Definitions", "Licenses Expire date", date_expire_epoch)

}

#IPS/FlowAV Engine   3.410  2017-03-24 16:25:00  manual    n/a
/^IPS/ && /FlowAV Engine /{

    # Generate in epoch the expiry-time (last-column) the 2016-11-16 & 15:45:00 (Expiration Date of IPS/FlowAV Engine)
    date_expire_epoch = getInEpoch($(NF-1), $NF)
    publishDateMetricIfExist("license-expiration", "IPS/FlowAV Engine", "Licenses Expire date", date_expire_epoch)

    # Generate in epoch the update-time (third-column) 2016-11-16 & 15:45:00 (Update Date of IPS/FlowAV Engine)
    date_update_epoch = getLastUpdateEpoch($0, "IPS/FlowAV Engine")
    publishDateMetricIfExist("package-last-update", "Last Update of the IPS/Flow AntiVirus Engine", "FortiGuard Services Last Update", date_update_epoch)

}

#Application Definitions  6.741  2015-12-01 02:30:00  manual    n/a
/^Application Definitions /{

    # Generate in epoch the expiry-time (last-column) the 2016-11-16 & 15:45:00 (Expiration Date of Application Definitions)
    date_expire_epoch = getInEpoch($(NF-1), $NF)
    publishDateMetricIfExist("license-expiration", "Application Definitions", "Licenses Expire date", date_expire_epoch)

    # Generate in epoch the update-time (third-column) 2016-11-16 & 15:45:00 (Update Date of Application Definitions)
    date_update_epoch = getLastUpdateEpoch($0, "Application Definitions")
    publishDateMetricIfExist("package-last-update", "Last Update of the Application Definitions", "FortiGuard Services Last Update", date_update_epoch)

}

#Industrial Attack Definitions  6.741  2015-12-01 02:30:00  manual    n/a
/^Industrial Attack Definitions /{

    # Generate in epoch the expiry-time (last-column) the 2016-11-16 & 15:45:00 (Expiration Date of Industrial Attack Definitions )
    date_expire_epoch = getInEpoch($(NF-1), $NF)
    publishDateMetricIfExist("license-expiration", "Industrial Attack Definitions", "Licenses Expire date", date_expire_epoch)

}

RuleMetadata

.builder(
  "cross_vendor_app_package_not_updated
package com.indeni.server.rules.library

import com.indeni.apidata.time.TimeSpan
import com.indeni.apidata.time.TimeSpan.TimePeriod
import com.indeni.ruleengine.expressions.conditions.GreaterThan
import com.indeni.ruleengine.expressions.core.{StatusTreeExpression, _}
import com.indeni.ruleengine.expressions.data._
import com.indeni.ruleengine.expressions.math.PlusExpression
import com.indeni.ruleengine.expressions.utility.NowExpression
import com.indeni.server.common.data.conditions.True
import com.indeni.server.params.ParameterDefinition
import com.indeni.server.params.ParameterDefinition.UIType
import com.indeni.server.rules._
import com.indeni.server.rules.library.core.PerDeviceRule
import com.indeni.server.sensor.models.managementprocess.alerts.dto.AlertSeverity

case class AppPackageNotUpdatedRule(context: RuleContext) extends PerDeviceRule with RuleHelper {

  private val highThresholdParameterName = "AppPackageNotUpdatedThreshold"
  private val highThresholdParameter = new ParameterDefinition(
    highThresholdParameterName,
    "",
    "App Package Not Updated Threshold",
    "If time since last app package update has elapsed more than this threshold, indeni will trigger an issue.",
    UIType.TIMESPAN,
    TimeSpan.fromDays(30)
  )

  override val metadata: RuleMetadata = RuleMetadata
    .builder(
      "cross_vendor_app_package_not_updated",
      "All Devices: App package needs update",
      "indeni will trigger an issue when app package has not been updated.",
      AlertSeverity.WARN
    )
    .configParameter(highThresholdParameter)
    .build()

  override def expressionTree: StatusTreeExpression = {
    val actualValue = TimeSeriesExpression[Double]("package-last-update").last.toTimeSpan(TimePeriod.SECOND)

    StatusTreeExpression(
      // Which objects to pull (normally, devices)
      SelectTagsExpression(context.metaDao, Set(DeviceKey), True),
      // What constitutes an issue
      StatusTreeExpression(
        // The additional tags we care about (we'll be including this in alert data)
        SelectTagsExpression(context.tsDao, Set("name"), withTagsCondition("package-last-update")),
        StatusTreeExpression(
          // The time-series we check the test condition against:
          SelectTimeSeriesExpression[Double](context.tsDao, Set("package-last-update"), denseOnly = false),
          // The condition which, if true, we have an issue. Checked against the time-series we've collected
          GreaterThan(NowExpression(),
                      PlusExpression[TimeSpan](actualValue, getParameterTimeSpanForTimeSeries(highThresholdParameter)))

          // The Alert Item to add for this specific item
        ).withSecondaryInfo(
            scopableStringFormatExpression("${scope(\"name\")}"),
            scopableStringFormatExpression("Last update on %s", timeSpanToDateExpression(actualValue)),
            title = "Affected Packages"
          )
          .asCondition()
      ).withoutInfo().asCondition()
    ).withRootInfo(
      getHeadline(),
      ConstantExpression("One or more app packages need update. See the list below."),
      ConditionalRemediationSteps(
        "Renew any app packages that need to be updated.",
        ConditionalRemediationSteps.VENDOR_FORTINET ->
          """
            |1. Login via ssh to the Fortinet firewall and execute the FortiOS “get system fortiguard-service status” command to list current update package versions and license expiry date and status.
            |2. Login via ssh to the Fortinet firewall and execute the FortiOS “diag autoupdate versions” and “diag autoupdate status” commands to get more details about the update policy and last update of the UTM services.
            |3. Login via https to the Fortinet firewall and go to the menu System > Dashboard > Status to locate the License Information widget. All subscribed services should have a green checkmark, indicating that connections are successful. A gray X indicates that the FortiGate unit cannot connect to the FortiGuard network, or that the FortiGate unit is not registered. A red X indicates that the FortiGate unit was able to connect but that a subscription has expired or has not been activated.
            |4. Verify that the Fortigate has internet access and then login via https to the Fortinet firewall to view the FortiGuard connection status by going to System > Config > FortiGuard menu. Select “Update Now” under AV & IPS Download Options to force a sync. In case of an update problem with the Web Filtering and Email Filtering expand the “Web Filtering and Email Filtering Options” and Change Port Selection to use an Alternate Port (8888) and press “Test Availability”. Wait a few minutes and verify the license health status.
            |5. If the registration does not appear after changing to Alternate Port mentioned to the above step, try pinging the FortiGuard services URL using command “exec ping service.fortiguard.net”. If that resolves to an IP then type the following commands:
            | - diag debug app update -1
            | - diag debug en
            | - exec update-now
            |If it does not resolve to an IP then this is a DNS issue.
            |Note: At the end disable the debug.
            |6. If you are using multiple VDOMS on the FortiGate, make sure that you have an Internet-facing VDOM set as the management vdom.
            |7. For more information about licensing review  the next  online article “Setting up FortiGuard services” : http://cookbook.fortinet.com/setting-fortiguard-services-54/
            |8. Contact Fortinet Technical support at https://support.fortinet.com/ for further assistance.""".stripMargin
      )
    )
  }
}