Syslog Servers In Use-paloaltonetworks-panos

best-practices
info
panos
paloaltonetworks
Syslog Servers In Use-paloaltonetworks-panos
0

#1

Syslog Servers In Use-paloaltonetworks-panos

Vendor: paloaltonetworks

OS: panos

Description:
Indeni will verify that certain syslog servers are configured on a monitored device.

Remediation Steps:
Modify the device’s configuration as required.

How does this work?
This script pulls the Palo Alto Networks firewall’s active configuration and extracts the configured Syslog servers from there.

Why is this important?
Tracking the currently configured Syslog servers on all devices is important to ensure consistent logging.

Without Indeni how would you find this?
An administrator may write a script to pull this data from devices and compare against a gold configuration.

panos-show_config_running-monitoring-xml

#! META
name: panos-show_config_running-monitoring-xml
description: Fetch the running config (xml)
type: monitoring
monitoring_interval: 60 minute
requires:
    vendor: paloaltonetworks
    os.name: panos

#! COMMENTS
certificate-expiration:
    why: |
        Palo Alto Networks firewalls use certificate for a variety of different purposes. One purpose, for example, is inbound SSL inspection. If the certificate used by the firewall expires, certain services may be unavailable to external users.
    how: |
        This script pulls the Palo Alto Networks firewall's active configuration, reviews the certificates saved and retrieves their subject and expiration date.
    without-indeni: |
        An administrator may manually review the certificates and their expiration dates, by looking at the web interface.
    can-with-snmp: true
    can-with-syslog: true
timezone:
    why: |
        Most configurations in Palo Alto Networks firewalls are synchronized across cluster members. Some are not, the timezone is one of them. It is important to verify that the timezone is the same on all cluster members to avoid confusion or issues.
    how: |
        This script pulls the Palo Alto Networks firewall's active configuration and extracts the timezone from there.
    without-indeni: |
        An administrator may write a script to pull this data from cluster members and compare it.
    can-with-snmp: false
    can-with-syslog: false
domain:
    why: |
        Most configurations in Palo Alto Networks firewalls are synchronized across cluster members. Some are not, the domain name is one of them. It is important to verify that the domain name is the same on all cluster members to avoid confusion or issues.
    how: |
        This script pulls the Palo Alto Networks firewall's active configuration and extracts the timezone from there.
    without-indeni: |
        An administrator may write a script to pull this data from cluster members and compare it.
    can-with-snmp: false
    can-with-syslog: false
login-banner:
    why: |
        Most configurations in Palo Alto Networks firewalls are synchronized across cluster members. Some are not, the login banner is one of them. It is important to verify that the login banner is the same on all cluster members to avoid confusion or issues.
    how: |
        This script pulls the Palo Alto Networks firewall's active configuration and extracts the timezone from there.
    without-indeni: |
        An administrator may write a script to pull this data from cluster members and compare it.
    can-with-snmp: false
    can-with-syslog: false
syslog-servers:
    why: |
        Tracking the currently configured Syslog servers on all devices is important to ensure consistent logging.
    how: |
        This script pulls the Palo Alto Networks firewall's active configuration and extracts the configured Syslog servers from there.
    without-indeni: |
        An administrator may write a script to pull this data from devices and compare against a gold configuration.
    can-with-snmp: false
    can-with-syslog: false
radius-servers:
    why: |
        Tracking the currently configured RADIUS servers on all devices is important to ensure consistent authentication and access.
    how: |
        This script pulls the Palo Alto Networks firewall's active configuration and extracts the configured RADIUS servers from there.
    without-indeni: |
        An administrator may write a script to pull this data from devices and compare against a gold configuration.
    can-with-snmp: false
    can-with-syslog: false
dns-servers:
    why: |
        Tracking the currently configured DNS servers on all devices is important to ensure consistent name resolution.
    how: |
        This script pulls the Palo Alto Networks firewall's active configuration and extracts the configured DNS servers from there.
    without-indeni: |
        An administrator may write a script to pull this data from devices and compare against a gold configuration.
    can-with-snmp: false
    can-with-syslog: false
ntp-servers:
    why: |
        Tracking the currently configured NTP servers on all devices is important to ensure consistent time sync.
    how: |
        This script pulls the Palo Alto Networks firewall's active configuration and extracts the configured NTP servers from there.
    without-indeni: |
        An administrator may write a script to pull this data from devices and compare against a gold configuration.
    can-with-snmp: false
    can-with-syslog: false
unencrypted-snmp-configured:
    why: |
        SNMPv2c is an unsecure protocol and should not be used. Users should prefer the more secure SNMPv3.
    how: |
        This script pulls the Palo Alto Networks firewall's active configuration and extracts the configured services from there.
    without-indeni: |
        An administrator may write a script to pull this data from devices and compare against a gold configuration.
    can-with-snmp: false
    can-with-syslog: false
telnet-enabled:
    why: |
        Telnet is an unsecure protocol and should not be used. Users may enable telnet unintentionally and should be alerted if they do so.
    how: |
        This script pulls the Palo Alto Networks firewall's active configuration and extracts the configured services from there.
    without-indeni: |
        An administrator may write a script to pull this data from devices and compare against a gold configuration.
    can-with-snmp: false
    can-with-syslog: false
http-server-enabled:
    why: |
        HTTP is an unsecure protocol and should not be used. Users may enable HTTP unintentionally and should be alerted if they do so.
    how: |
        This script pulls the Palo Alto Networks firewall's active configuration and extracts the configured services from there.
    without-indeni: |
        An administrator may write a script to pull this data from devices and compare against a gold configuration.
    can-with-snmp: false
    can-with-syslog: false
license-elements-used:
    skip-documentation: true
app-update-acceptable-lag:
    skip-documentation: true

#! REMOTE::HTTP
url: /api?type=op&cmd=<show><config><running></running></config></show>&key=${api-key}
protocol: HTTPS

#! PARSER::XML
_vars:
    root: /response/result/config
_metrics:
    -
        _groups:
            ${root}/shared/certificate/entry:
                _value.double:
                    _text: "expiry-epoch"
                _tags:
                    name:
                        _text: "subject"
                    "im.name":
                        _constant: "certificate-expiration"
                    "live-config":
                        _constant: "true"
                    "display-name":
                        _constant: "Certificate Expiration"
                    "im.dstype.displayType":
                        _constant: "date"
                    "im.identity-tags":
                        _constant: "name"
    -
        _value.complex:
            value:
                _text: "${root}/devices/entry/deviceconfig/system/timezone"
        _tags:
            "im.name":
                _constant: "timezone"
            "live-config":
                _constant: "true"
            "display-name":
                _constant: "Timezone"
    -
        _value.complex:
            value:
                _text: "${root}/devices/entry/deviceconfig/system/domain"
        _tags:
            "im.name":
                _constant: "domain"
            "live-config":
                _constant: "true"
            "display-name":
                _constant: "Domain"
    -
        _value.complex:
            value:
                _text: "${root}/devices/entry/deviceconfig/system/login-banner"
        _tags:
            "im.name":
                _constant: "login-banner"
            "live-config":
                _constant: "true"
            "display-name":
                _constant: "Login Banner"
    -
        _tags:
            "im.name":
                _constant: "app-update-acceptable-lag"
            "live-config":
                _constant: "true"
            "display-name":
                _constant: "Application Packages - Acceptable Lag"
            "im.dstype.displayType":
                _constant: "duration"
        _temp:
            isweekly:
                _count: "${root}/devices/entry/deviceconfig/system/update-schedule/threats/recurring/weekly"
            ishourly:
                _count: "${root}/devices/entry/deviceconfig/system/update-schedule/threats/recurring/hourly"
            isdaily:
                _count: "${root}/devices/entry/deviceconfig/system/update-schedule/threats/recurring/daily"
            threshold:
                # This is a hack. The threshold may, or may not exist.
                # If we were to refer to it directly and it didn't exist, the entire metric
                # would have been aborted. So instead, we "name" the text of it, as well as
                # another, related node. If the threshold exists, we'll be getting its value.
                # If it doesn't, we'll get "recurring" (the name of the node in the second path)
                _name: "${root}/devices/entry/deviceconfig/system/update-schedule/threats/recurring/threshold/text() | ${root}/devices/entry/deviceconfig/system/update-schedule/threats/recurring[not(threshold)]"
        _transform:
            _value.double: |
                    {
                        # The acceptable lag depends on the kind of schedule used
                        acceptablelag=0
                        if (temp("isweekly") == "1") {
                            acceptablelag=8*24*3600
                        } else if (temp("ishourly") == "1") {
                            acceptablelag=2*3600
                        } else if (temp("isdaily") == "1") {
                            acceptablelag=47*3600
                        }

                        # Add threshold
                        if (temp("threshold") != "recurring") {
                            acceptablelag = acceptablelag + (temp("threshold") * 3600)
                        }

                        print acceptablelag
                    }
    -
        _tags:
            "im.name":
                _constant: "panw-app-update-action"
            "live-config":
                _constant: "true"
            "display-name":
                _constant: "Application Packages - Update Action"
            "im.dstype.displayType":
                _constant: "string"
        _value.complex:
            value:
                _text: "${root}/devices/entry/deviceconfig/system/update-schedule/threats/recurring/*/action"
    -
        _groups:
            "${root}//syslog/entry/server/entry":
                _value.complex:
                    "host":
                        _text: "server"
                    "severity":
                        _text: "facility"
                _tags:
                    "im.name":
                        _constant: "syslog-servers"
                    "live-config":
                        _constant: "true"
                    "display-name":
                        _constant: "Syslog Servers"
        _value: complex-array
    -
        _groups:
            "${root}//radius/entry/server/entry":
                _value.complex:
                    "host":
                        _text: "ip-address"
                    "port":
                        _text: "port"
                _tags:
                    "im.name":
                        _constant: "radius-servers"
                    "live-config":
                        _constant: "true"
                    "display-name":
                        _constant: "RADIUS Servers"
        _value: complex-array
    -
        _groups:
            "/response/result/config/devices/entry/deviceconfig/system/dns-setting/servers/*":
                _value.complex:
                    "ipaddress":
                        _text: .
                _tags:
                    "im.name":
                        _constant: "dns-servers"
                    "live-config":
                        _constant: "true"
                    "display-name":
                        _constant: "DNS Servers"
        _value: complex-array
    -
        _groups:
            "/response/result/config/devices/entry/deviceconfig/system/ntp-servers/*/ntp-server-address":
                _value.complex:
                    "ipaddress":
                        _text: .
                _tags:
                    "im.name":
                        _constant: "ntp-servers"
                    "live-config":
                        _constant: "true"
                    "display-name":
                        _constant: "NTP Servers"
        _value: complex-array
    -
        _value.double:
            _count: /response/result/config/devices/entry/vsys/entry
        _tags:
            "name":
                _constant: "vsys"
            "im.name":
                _constant: "license-elements-used"
            "live-config":
                _constant: "true"
            "display-name":
                _constant: "Licenses - Usage"
            "im.dstype.displayType":
                _constant: "number"
            "im.identity-tags":
                _constant: "name"
    -
        _tags:
            "im.name":
                _constant: "unencrypted-snmp-configured"
        _temp:
            hasSnmpV2c:
                _count: "/response/result/config/devices/entry/deviceconfig/system/snmp-setting/access-setting/version/v2c"
        _transform:
            _value.complex:
                value: |
                    {
                        if (temp("hasSnmpV2c") == "1") {
                            print "true"
                        } else {
                            print "false"
                        }
                    }
    -
        _tags:
            "im.name":
                _constant: "telnet-enabled"
        _temp:
            hasTelnetAtNo:
                _count: "${root}/devices/entry/deviceconfig/system/service/disable-telnet[text() = 'no']"
        _transform:
            _value.complex:
                value: |
                    {
                        if (temp("hasTelnetAtNo") == "1") {
                            print "true"
                        } else {
                            print "false"
                        }
                    }
    -
        _tags:
            "im.name":
                _constant: "http-server-enabled"
        _temp:
            hasHttpAtNo:
                _count: "${root}/devices/entry/deviceconfig/system/service/disable-http[text() = 'no']"
        _transform:
            _value.complex:
                value: |
                    {
                        if (temp("hasHttpAtNo") == "1") {
                            print "true"
                        } else {
                            print "false"
                        }
                    }

verification_syslog_servers_in_use

package com.indeni.server.rules.library

import com.indeni.ruleengine.Scope.{Scope, ScopeValueHelper}
import com.indeni.ruleengine.expressions.core._
import com.indeni.ruleengine.expressions.data._
import com.indeni.ruleengine.expressions.scope.ScopableExpression
import com.indeni.ruleengine.expressions.utility.IsEmptyExpression.IsEmptyExpressionHelper
import com.indeni.ruleengine.expressions.utility.SeqDiffWithoutOrderExpression
import com.indeni.ruleengine.expressions.{Expression, conditions}
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.config.expressions.DynamicParameterExpression
import com.indeni.server.rules.library.core.PerDeviceRule
import com.indeni.server.rules.{RuleMetadata, _}
import com.indeni.server.sensor.models.automationpolicy.AutomationPolicyItemAlertSetting
import com.indeni.server.sensor.models.managementprocess.alerts.dto.AlertSeverity


/**
  * Created by amir on 19/02/2017.
  */
case class SyslogServersInUseComplianceCheckRule() extends PerDeviceRule with RuleHelper {

  private val linesParameterName = "syslog_config_lines"
  private val linesParameter = new ParameterDefinition(
    linesParameterName,
    "",
    "Syslog servers config needed (multi-line, <ip-address>, <min-severity>)",
    "List the syslog servers need to be configured, and their minimal severity.\ne.g. 1.1.1.1, info.",
    UIType.MULTILINE_TEXT,
    "")


  override def expressionTree(context: RuleContext): StatusTreeExpression = {
    val linesExpected = DynamicParameterExpression.withConstantDefault(linesParameter.getName, Seq[Seq[String]]()).withLazy

    val snapshotKey = "syslog-servers"
    val missings =
      SeqDiffWithoutOrderExpression(
        MultiSnapshotExtractVectorExpression(SnapshotExpression(snapshotKey).asMulti().mostRecent().value(), "host", "severity"),
        linesExpected
      ).missings
        .withLazy

    val missingLineHeadline = new ScopableExpression[String] {
      override protected def evalWithScope(time: Long, scope: Scope): String = scope.getVisible("syslogConfig").get.asInstanceOf[Seq[String]].mkString(", ")
      override def args: Set[Expression[_]] = Set()
    }

    StatusTreeExpression(
      // Which objects to pull (normally, devices)
      SelectTagsExpression(context.metaDao, Set(DeviceKey), True),

      // What constitutes an issue
      StatusTreeExpression(
        // The snapshot we check the test condition against:
        SelectSnapshotsExpression(context.snapshotsDao, Set(snapshotKey)).multi(),

        // The condition which, if true, we have an issue. Checked against the snapshots we've collected
        missings.nonEmpty,
        multiInformers = Set(
          MultiIssueInformer(
            missingLineHeadline,
            EMPTY_STRING,
            "Missing configuration"
          ).iterateOver(
            missings,
            "syslogConfig",
            conditions.True
          ))

        // Details of the alert itself
      ).withRootInfo(
        getHeadline(),
        ConstantExpression("Indeni has found that some syslog servers are missing or misconfigured. Check the list below."),
        ConditionalRemediationSteps("Modify the device's configuration as required.",
          ConditionalRemediationSteps.OS_NXOS ->
            """|1. Check if the IP address of the syslog server is accessible. Use theVRF management option if the Mangement VRF is configured to access the syslog servers. In this case use the "ping <dest-ip> vrf management" command to ping the server otherwise ping the server without the vrf option.
               |2. Check that the appropriate logging level is enabled to send logging messages. Use the "show logging info" NX-OS command. If the logging level is not appropriate, then set the appropriate level by using the "logging level <feature> <log-level>" NX-OS command.
               |3. It is a best practice to have at least one and no more than three, syslog servers configured.
               |4. For more information please review: <a target="_blank" href="https://www.cisco.com/c/en/us/td/docs/switches/datacenter/nexus5000/sw/system_management/502_n1_1/b_Cisco_n5k_system_mgmt_cg_rel_502_n1_1/Cisco_n5k_system_mgmt_cg_rel_502_n1_1_chapter9.html">Cisco NX-OS configuration guide</a>.""".stripMargin,
          ConditionalRemediationSteps.VENDOR_JUNIPER ->
            """|1. On the device command line interface execute "show system syslog" command to review system log configuration.
               |2. Check if the syslog server is accessible.
               |3. Check if the severity level is set properly to ensure that the traffic log messages are captured.
               |4. Consider specifying two remote syslog servers to which system logs are sent.
               |5. Review the following article on Juniper TechLibrary for more information: <a target="_blank" href="https://kb.juniper.net/InfoCenter/index?page=content&id=KB16502&actp=METADATA">SRX Getting Started - Configure System Logging</a>.""".stripMargin
        )
      ).asCondition()
    ).withoutInfo()
  }

  /**
    * @return The rule's metadata.
    */
  override def metadata: RuleMetadata =
    RuleMetadata.builder(
      "verification_syslog_servers_in_use",
      "Compliance Check: Syslog Servers In Use",
      "Indeni will verify that certain syslog servers are configured on a monitored device.",
      AlertSeverity.INFO)
      .defaultAction(AutomationPolicyItemAlertSetting.NEVER)
      .configParameter(linesParameter)
      .build()
}


#2