diff --git a/.circleci/config.yml b/.circleci/config.yml index 4786b41..1dedbc9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -28,13 +28,48 @@ jobs: command: docker login -u $DOCKER_USER -p $DOCKER_PASS - run: name: Build Docker image - command: pushd package; docker build -f Dockerfile --build-arg RH_ORG=$RH_ORG --build-arg RH_ACTIVATION=$RH_ACTIVATION -t $IMAGE_NAME:build . + command: docker build -f package/Dockerfile --build-arg RH_ORG=$RH_ORG --build-arg RH_ACTIVATION=$RH_ACTIVATION -t $IMAGE_NAME:build package - run: name: Tag Docker image command: docker tag $IMAGE_NAME:build $IMAGE_NAME:$CIRCLE_SHA1 + - run: + name: Tag Docker image + command: docker tag $IMAGE_NAME:build $IMAGE_NAME:edge - run: name: Push Docker image command: docker push $IMAGE_NAME:$CIRCLE_SHA1 + - run: + name: Push Docker image + command: docker push $IMAGE_NAME:edge + build-egb: + environment: + IMAGE_NAME: rfaircloth/scs + docker: + - image: circleci/buildpack-deps:stretch + steps: + - checkout + - run: git submodule sync + - run: git submodule update --init --recursive + - setup_remote_docker: + docker_layer_caching: true + - run: + name: Docker Login + command: docker login -u $DOCKER_USER -p $DOCKER_PASS + - run: + name: Build Docker image + command: docker build -f perftests/bundlesrv/Dockerfile -t $IMAGE_NAME:egb-build perftests/bundlesrv + - run: + name: Tag Docker image + command: docker tag $IMAGE_NAME:egb-build $IMAGE_NAME:egb-$CIRCLE_SHA1 + - run: + name: Tag Docker image + command: docker tag $IMAGE_NAME:egb-build $IMAGE_NAME:egb-edge + - run: + name: Push Docker image + command: docker push $IMAGE_NAME:egb-$CIRCLE_SHA1 + - run: + name: Push Docker image + command: docker push $IMAGE_NAME:egb-edge dgoss: environment: IMAGE_NAME: rfaircloth/scs @@ -103,9 +138,7 @@ jobs: - run: name: Docker Compose build command: | - docker-compose build \ - --build-arg RH_ACTIVATION=$RH_ACTIVATION \ - --build-arg RH_ORG=$RH_ORG + docker-compose build - run: name: Docker Compose up command: docker-compose up --abort-on-container-exit @@ -136,10 +169,8 @@ jobs: pip install -r requirements.txt python clair_to_junit_parser.py "/clair-reports/$IMAGE_NAME:$CIRCLE_SHA1.json" --output test-results/results.xml when: on_fail -# - store_test_results: -# path: test-results/results.xml - - store_artifacts: - path: test-results + - store_test_results: + path: test-results/results.xml - store_artifacts: path: /clair-reports @@ -168,6 +199,7 @@ workflows: build-publish: jobs: - build + - build-egb - dgoss: requires: - build diff --git a/.env.template b/.env.template index 8950cae..5a9bda1 100644 --- a/.env.template +++ b/.env.template @@ -16,6 +16,6 @@ SPLUNK_HEC_STATSURL=https://splunk:8088/services/collector/event SPLUNK_CONNECT_METHOD=hec SPLUNK_DEFAULT_INDEX=main SPLUNK_METRICS_INDEX=metrics -SPLUNK_APPS_URL=https://splunkbase.splunk.com/app/2757/release/6.1.1/download,https://splunkbase.splunk.com/app/3245/release/1.0/download,https://splunkbase.splunk.com/app/1620/release/3.4.0/download,https://splunkbase.splunk.com/app/1467/release/2.5.8/download +SPLUNK_APPS_URL=https://splunkbase.splunk.com/app/2757/release/6.1.1/download,https://splunkbase.splunk.com/app/3245/release/1.0/download,https://splunkbase.splunk.com/app/1620/release/3.4.0/download,https://splunkbase.splunk.com/app/1467/release/2.5.8/download,https://splunkbase.splunk.com/app/2846/release/1.6.0/download SPLUNKBASE_USERNAME=username SPLUNKBASE_PASSWORD=password diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..ef960bb --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,2 @@ +* @rfaircloth-splunk +package/etc/ @rfaircloth @mbonsack \ No newline at end of file diff --git a/.gitignore b/.gitignore index d96805f..68dbac4 100644 --- a/.gitignore +++ b/.gitignore @@ -303,9 +303,86 @@ tags # Persistent undo [._]*.un~ +<<<<<<< HEAD +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +/test-results/ +!/package/scripts/switch_transport.sh +!/package/scripts/splunkmetrics.sh +!/package/scripts/ +.ecs +======= /test-results/ /.idea/workspace.xml /.idea/tasks.xml !/package/scripts/switch_transport.sh !/package/scripts/splunkmetrics.sh !/package/scripts/ +>>>>>>> master diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..6310177 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..335ef34 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,100 @@ +# Contributing + +### Past / Active(marked as *) Contributors +rfaircloth* +mbonsack* +rfipro* +Hurricane Labs* + + +## Code of conduct + +###Contributor License Agreement + +At the moment, we can only accept pull requests submitted from either: +* Splunk employees or +* Individuals that have signed our contribution agreement + +If you wish to be a contributing member of our community, please see the agreement [for individuals](https://www.splunk.com/goto/individualcontributions) or [for organizations](https://www.splunk.com/goto/contributions). + +### Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +### Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + + +### Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +### Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +### Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at tonyl@splunk.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +### Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ + +## Filing issues + +Use project issue tracker + +## Contributing code + +Future Docs \ No newline at end of file diff --git a/docker-compose-perf.yml b/docker-compose-perf.yml new file mode 100644 index 0000000..67f3844 --- /dev/null +++ b/docker-compose-perf.yml @@ -0,0 +1,77 @@ +#Splunk Connect for Syslog (SC4S) by Splunk, Inc. +# +#To the extent possible under law, the person who associated CC0 with +#Splunk Connect for Syslog (SC4S) has waived all copyright and related or neighboring rights +#to Splunk Connect for Syslog (SC4S). +# +#You should have received a copy of the CC0 legalcode along with this +#work. If not, see . +version: "3" +services: + sc4s: + image: rfaircloth/scs:edge + build: + context: ./package + args: + RH_ORG: ${RH_ORG} + RH_ACTIVATION: ${RH_ACTIVATION} + hostname: sc4s + ports: + - "514" + - "601" + - "514/udp" + - "5514" + - "5514/udp" + links: + - splunk + environment: + - SPLUNK_HEC_URL=${SPLUNK_HEC_URL} + - SPLUNK_HEC_STATSURL=${SPLUNK_HEC_STATSURL} + - SPLUNK_HEC_TOKEN=${SPLUNK_HEC_TOKEN} + - SPLUNK_CONNECT_METHOD=${SPLUNK_CONNECT_METHOD} + - SPLUNK_DEFAULT_INDEX=${SPLUNK_DEFAULT_INDEX} + - SPLUNK_METRICS_INDEX=${SPLUNK_DEFAULT_INDEX} +# logging: +# driver: splunk +# options: +# splunk-token: a778f63a-5dff-4e3c-a72c-a03183659e94 +# splunk-url: https://splunk:8088/services/collector/event +# splunk-index: main +# splunk-insecureskipverify: true +# splunk-verify-connection: false + splunk: + image: splunk/splunk:latest + hostname: splunk + ports: + - "8000:8000" + - "8088:8088" + - "8089:8089" + environment: + - SPLUNK_HEC_TOKEN=${SPLUNK_HEC_TOKEN} + - SPLUNK_PASSWORD=${SPLUNK_PASSWORD} + - SPLUNK_START_ARGS=${SPLUNK_START_ARGS} + - SPLUNK_APPS_URL=${SPLUNK_APPS_URL} + - SPLUNKBASE_USERNAME=${SPLUNKBASE_USERNAME} + - SPLUNKBASE_PASSWORD=${SPLUNKBASE_PASSWORD} +# logging: +# driver: splunk +# options: +# splunk-token: a778f63a-5dff-4e3c-a72c-a03183659e94 +# splunk-url: https://splunk:8088/services/collector/event +# splunk-index: main +# splunk-insecureskipverify: true +# splunk-verify-connection: false + egbundles: + image: rfaircloth/scs:egb-edge + hostname: egbundles + build: + context: perftests/bundlesrv + eventgen: + image: rfaircloth/eventgen:edge + command: standalone + ports: + - "9500:9500" + links: + - egbundles + - sc4s + diff --git a/docker-compose.yml b/docker-compose.yml index 94a8320..f13c181 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,15 +17,15 @@ services: - sc4s-tests:/work/tests - sc4s-results:/work/test-results environment: - - SPLUNK_PASSWORD + - SPLUNK_PASSWORD=${SPLUNK_PASSWORD} sc4s: image: rfaircloth/scs:latest build: context: ./package args: - RH_ORG: $RH_ORG - RH_ACTIVATION: $RH_ACTIVATION + RH_ORG: ${RH_ORG} + RH_ACTIVATION: ${RH_ACTIVATION} hostname: sc4s ports: - "514" @@ -38,12 +38,12 @@ services: links: - splunk environment: - - SPLUNK_HEC_URL - - SPLUNK_HEC_STATSURL - - SPLUNK_HEC_TOKEN - - SPLUNK_CONNECT_METHOD - - SPLUNK_DEFAULT_INDEX - - SPLUNK_METRICS_INDEX + - SPLUNK_HEC_URL=${SPLUNK_HEC_URL} + - SPLUNK_HEC_STATSURL=${SPLUNK_HEC_STATSURL} + - SPLUNK_HEC_TOKEN=${SPLUNK_HEC_TOKEN} + - SPLUNK_CONNECT_METHOD=${SPLUNK_CONNECT_METHOD} + - SPLUNK_DEFAULT_INDEX=${SPLUNK_DEFAULT_INDEX} + - SPLUNK_METRICS_INDEX=${SPLUNK_DEFAULT_INDEX} # logging: # driver: splunk # options: @@ -60,12 +60,12 @@ services: - "8088:8088" - "8089:8089" environment: - - SPLUNK_HEC_TOKEN - - SPLUNK_PASSWORD - - SPLUNK_START_ARGS - - SPLUNK_APPS_URL - - SPLUNKBASE_USERNAME - - SPLUNKBASE_PASSWORD + - SPLUNK_HEC_TOKEN=${SPLUNK_HEC_TOKEN} + - SPLUNK_PASSWORD=${SPLUNK_PASSWORD} + - SPLUNK_START_ARGS=${SPLUNK_START_ARGS} + - SPLUNK_APPS_URL=${SPLUNK_APPS_URL} + - SPLUNKBASE_USERNAME=${SPLUNKBASE_USERNAME} + - SPLUNKBASE_PASSWORD=${SPLUNKBASE_PASSWORD} volumes: - ./splunk/SA-syslog-ng:/opt/splunk/etc/apps/SA-syslog-ng # logging: diff --git a/package/Dockerfile b/package/Dockerfile index 5ecc921..7c47a5a 100644 --- a/package/Dockerfile +++ b/package/Dockerfile @@ -76,18 +76,18 @@ RUN cd /tmp ;\ ENV DEBCONF_NONINTERACTIVE_SEEN=true ENV SPLUNK_CONNECT_METHOD=hec -ENV SYSLOGNG_HEC_WORKERS=3 +ENV SYSLOGNG_HEC_WORKERS=10 RUN source scl_source enable rh-python36 ; curl -fsSL https://goss.rocks/install | GOSS_VER=v0.3.7 sh COPY goss.yaml /etc/goss.yaml COPY --from=0 /opt/syslog-ng /opt/syslog-ng -COPY scripts/splunkmetrics.sh /opt/syslog-ng/sbin/splunkmetrics.sh COPY etc/syslog-ng.conf /opt/syslog-ng/etc/syslog-ng.conf COPY etc/conf.d /opt/syslog-ng/etc/conf.d COPY etc/context /opt/syslog-ng/etc/context COPY sbin/entrypoint.sh /sbin/entrypoint.sh +RUN mkdir -p /opt/syslog-ng/var/data/disk-buffer RUN source scl_source enable rh-python36 ;/opt/syslog-ng/sbin/syslog-ng -V RUN source scl_source enable rh-python36 ;/opt/syslog-ng/sbin/syslog-ng -t RUN mkdir -p /var/log/syslog-ng/data/disk-buffer diff --git a/package/etc/conf.d/destinations/d_destinations.conf b/package/etc/conf.d/destinations/d_destinations.conf index 1d373d4..6d4f9d4 100644 --- a/package/etc/conf.d/destinations/d_destinations.conf +++ b/package/etc/conf.d/destinations/d_destinations.conf @@ -17,18 +17,18 @@ destination d_hec { method("POST") log-fifo-size(`splunk-log-fifo-size`) workers(`SYSLOGNG_HEC_WORKERS`) - batch-lines(1000) + batch-lines(500) batch-bytes(512Kb) - batch-timeout(1000) - timeout(5) + batch-timeout(3) + timeout(15) user_agent("syslog-ng User Agent") user("syslog-ng") password("`SPLUNK_HEC_TOKEN`") -# persist-name("t_standard") -# disk-buffer(mem-buf-length(5000) -# disk-buf-size(107374182400) -# reliable(no) -# dir("/var/log/syslog-ng/data/disk-buffer")) + persist-name("splunk") + disk-buffer(mem-buf-length(500) + disk-buf-size(20000) + reliable(no) + dir("/opt/syslog-ng/var/data/disk-buffer/")) tls(peer-verify(no) # ca-dir("dir") # ca-file("ca") @@ -48,3 +48,28 @@ destination d_hec { fields.*)') ); }; + +destination d_hecmetrics { + http( + url("`SPLUNK_HEC_URL`") + method("POST") + batch-lines(5) + batch-bytes(512Kb) + batch-timeout(1) + timeout(15) + user_agent("syslog-ng User Agent") + user("syslog-ng") + password("`SPLUNK_HEC_TOKEN`") + persist-name("splunk_metrics") + tls(peer-verify(no) +# ca-dir("dir") +# ca-file("ca") +# cert-file("cert") +# cipher-suite("cipher") +# key-file("key") +# peer-verify(yes|no) +# ssl-version() + ) + body('$MESSAGE') + ); + }; diff --git a/package/etc/conf.d/filters/cisco_asa_tradditional.conf b/package/etc/conf.d/filters/cisco_asa_tradditional.conf index a912baf..57d25ce 100644 --- a/package/etc/conf.d/filters/cisco_asa_tradditional.conf +++ b/package/etc/conf.d/filters/cisco_asa_tradditional.conf @@ -20,5 +20,5 @@ log { destination(d_hec); #--HEC-- - flags(final); + flags(flow-control,final); }; diff --git a/package/etc/conf.d/filters/cisco_ios.conf b/package/etc/conf.d/filters/cisco_ios.conf index 98427f1..cac0bb7 100644 --- a/package/etc/conf.d/filters/cisco_ios.conf +++ b/package/etc/conf.d/filters/cisco_ios.conf @@ -12,5 +12,5 @@ log { rewrite { r_set_splunk_basic(template("t_msg_only"))}; #--HEC-- destination(d_hec); #--HEC-- - flags(final); + flags(flow-control,final); }; diff --git a/package/etc/conf.d/filters/fortinet_fgt.conf b/package/etc/conf.d/filters/fortinet_fgt.conf new file mode 100644 index 0000000..f862fa9 --- /dev/null +++ b/package/etc/conf.d/filters/fortinet_fgt.conf @@ -0,0 +1,40 @@ +log { + source(s_default-ports); + + filter {tags("fgt_log") + or message('devid=\"?F[G|W|6K].+type=\"?(traffic|utm|event)'); + }; + + parser { + kv-parser(prefix(".kv.")); + date-parser(format("%Y-%m-%d:%H:%M:%S") template("${.kv.date}:${.kv.time}")); + }; + + rewrite { set("${.kv.devname}", value("HOST")); }; + rewrite { subst('<\d+>(.*)' "$1" value("MSG")); }; + + #set the source type based on program field and lookup index from the splunk context csv + if (match("traffic" value(".kv.type"))) { + parser {p_add_context_splunk(key("fgt_traffic")); }; + } elif (match("utm" value(".kv.type"))) { + parser {p_add_context_splunk(key("fgt_utm")); }; + } elif (match("event" value(".kv.type"))) { + parser {p_add_context_splunk(key("fgt_event")); }; + } else { + parser {p_add_context_splunk(key("fgt_log")); }; + }; + + rewrite { + #drop the header + subst('date=[^ ]+ time=[^ ]+ devname=.+ (devid.*)', '$1', value("MESSAGE")); + #Strip empty fields because SEDCMD can't when we use event endpoint + subst('([^\= ]+=(?: |\"\"|-|\"-") ?)', '', value("MESSAGE")); + }; + + #rewrite the final message for splunk json + #sourcetype and index are set in the filter defaults won't be used + rewrite {r_set_splunk_basic(template("t_msg_only")) }; #--HEC-- + destination(d_hec); #--HEC-- + + flags(flow-control,final); +}; diff --git a/package/etc/conf.d/filters/paloalto_networks.conf b/package/etc/conf.d/filters/paloalto_networks.conf index 1ef160c..a3e1016 100644 --- a/package/etc/conf.d/filters/paloalto_networks.conf +++ b/package/etc/conf.d/filters/paloalto_networks.conf @@ -57,5 +57,5 @@ log { destination(d_hec); #--HEC-- - flags(final); + flags(flow-control,final); }; diff --git a/package/etc/context/splunk_index.csv b/package/etc/context/splunk_index.csv index 75b98d6..97cf982 100644 --- a/package/etc/context/splunk_index.csv +++ b/package/etc/context/splunk_index.csv @@ -2,6 +2,14 @@ cisco:asa,index,main cisco:asa,sourcetype,cisco:asa cisco:ios,index,main cisco:ios,sourcetype,cisco:ios +fgt_event,sourcetype,fgt_event +fgt_event,index,main +fgt_log,sourcetype,fgt_log +fgt_log,index,main +fgt_traffic,sourcetype,fgt_traffic +fgt_traffic,index,main +fgt_utm,sourcetype,fgt_utm +fgt_utm,index,main pan:traffic,index,main pan:threat,index,main pan:system,index,main @@ -18,5 +26,9 @@ pan:hipwatch,sourcetype,pan:hipwatch pan:correlation,sourcetype,pan:correlation pan:userid,sourcetype,pan:userid pan:unknown,sourcetype,pan:unknown -syslogng-fallback,index,syslogng-fallback -syslogng-fallback,sourcetype,syslogng-fallback +syslog-ng:events,index,main +syslog-ng:events,sourcetype,syslog-ng:events +syslog-ng:fallback,index,main +syslog-ng:fallback,sourcetype,syslog-ng:fallback +syslog-ng:metrics,index,em_metrics +syslog-ng:metrics,sourcetype,httpevent \ No newline at end of file diff --git a/package/etc/syslog-ng.conf b/package/etc/syslog-ng.conf index ab28af9..565b79e 100644 --- a/package/etc/syslog-ng.conf +++ b/package/etc/syslog-ng.conf @@ -15,7 +15,7 @@ options { log_msg_size (65536); - flush_lines (0); + flush_lines (100); time_reopen (10); log_fifo_size (10000); chain_hostnames (off); @@ -24,6 +24,13 @@ options { dns-cache(no); create_dirs (no); keep-hostname (yes); + create_dirs(yes); + dir_perm(0750); + stats-freq(30); + stats-level(1); + stats-max-dynamics(2000); + normalize-hostnames(yes); + on-error(fallback-to-string); }; # =============================================================================================== @@ -54,10 +61,10 @@ options { # =============================================================================================== @define ip-version 4 @define splunk-max-connections 1000 -@define splunk-log-fifo-size 10000 -@define splunk-fetch-limit 100 +@define splunk-log-fifo-size 180000000 +@define splunk-fetch-limit 20000 # make sure splunk-window-size >= splunk-max-connections * splunk-fetch-limit -@define splunk-window-size 100000 +@define splunk-window-size 20000000 @define splunk-rcvbuf 425984 @define default-timezone "GMT" @@ -70,6 +77,45 @@ options { @include "conf.d/sources/*.conf" @include "conf.d/blocks/*.conf" @include "conf.d/destinations/*.conf" + +log { + source(s_internal); + + if (match("^Log statistics; " value("MESSAGE"))) { + + parser {p_add_context_splunk(key("syslog-ng:metrics")); }; + rewrite { + subst('(?:Log statistics; )?(?[^= ]+)=\x27(?[^\(]+)\((?[^,\)]+)(?:,(?[^,]+),(?[^\)]+))?\)\=(?\d+)\x27(?:, )?', + ' + {"time": "$S_UNIXTIME.$S_MSEC", + "event": "metric", + "host": "$HOST", + "index": "${.splunk.index}", + "source": "internal", + "sourcetype": "${.splunk.sourcetype}", + "fields": { + "source_name": "${SourceName}", + "source_instance": "${SourceInstance}", + "state": "${State}", + "type": "${Type}", + "_value": ${Number}, + "metric_name": "syslogng.${SourceId}" + } + } + ', + value("MESSAGE") flags("utf8" "global") + ); + }; + destination(d_hecmetrics); #--HEC-- + } else { + parser {p_add_context_splunk(key("syslog-ng:events")); }; + rewrite {r_set_splunk_basic(template("t_msg_only")) }; #--HEC-- + destination(d_hec); #--HEC-- + }; + flags(final); +}; + + @include "conf.d/prefilters/*.conf" @include "conf.d/filters/*.conf" @@ -79,9 +125,10 @@ options { log { source(s_default-ports); + parser {p_add_context_splunk(key("syslog-ng:fallback")); }; rewrite { r_set_splunk(template("t_JSON"))}; #--HEC-- destination(d_hec); #--HEC-- - flags(fallback); + flags(flow-control,fallback); }; diff --git a/package/sbin/entrypoint.sh b/package/sbin/entrypoint.sh index 3578897..5d37dd1 100755 --- a/package/sbin/entrypoint.sh +++ b/package/sbin/entrypoint.sh @@ -7,5 +7,4 @@ #Run syslog mkdir /opt/syslog-ng/var rm /opt/syslog-ng/var/syslog-ng.ctl || true -/opt/syslog-ng/sbin/syslog-ng --process-mode=background -/opt/syslog-ng/sbin/splunkmetrics.sh +/opt/syslog-ng/sbin/syslog-ng -F diff --git a/package/scripts/splunkmetrics.sh b/package/scripts/splunkmetrics.sh deleted file mode 100755 index 7a497eb..0000000 --- a/package/scripts/splunkmetrics.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash -#Copyright 2019 Splunk, Inc. -# -#Use of this source code is governed by a BSD-2-clause-style -#license that can be found in the LICENSE-BSD2 file or at -#https://opensource.org/licenses/BSD-2-Clause -sleep 30 -while sleep 10 -do - TS=$(date +"%s") - tmpfilecsv=$(mktemp /tmp/syslog-ng-stats-XXXXXXX-csv) - tmpfilejson=$(mktemp /tmp/syslog-ng-stats-XXXXXXX-json) - /opt/syslog-ng/sbin/syslog-ng-ctl query get "*" --reset | tail -n +2 | grep \^. | grep -v "^The selected counters" >$tmpfilecsv - IFS=';' - while read -r SourceName SourceId SourceInstance State Type Number - do - echo "{ - \"time\":\"$TS\", - \"event\":\"metric\", - \"source\":\"syslog-ng\", - \"host\":\"$HOSTNAME\", - \"index\":\"$SPLUNK_METRICS_INDEX\", - \"fields\":{ - \"SourceId\":\"$SourceId\", - \"SourceInstance\":\"$SourceInstance\", - \"State\":\"$State\", - \"Type\":\"$Type\", - \"_value\":$Number, - \"metric_name\":\"$SourceName\" - } - } ">>$tmpfilejson - done < $tmpfilecsv - - curl -s -S -k $SPLUNK_HEC_STATSURL -H "Authorization: Splunk $SPLUNK_HEC_TOKEN" -d "@$tmpfilejson" - rm $tmpfilejson - rm $tmpfilecsv -done diff --git a/perftests/bundlesrv/Dockerfile b/perftests/bundlesrv/Dockerfile new file mode 100644 index 0000000..e5ed403 --- /dev/null +++ b/perftests/bundlesrv/Dockerfile @@ -0,0 +1,14 @@ +FROM registry.access.redhat.com/ubi7/ubi as build + +COPY scenarios /scenarios + +RUN yum install zip -y + +RUN mkdir /bundles + +RUN cd /scenarios;./build.sh;cp *.zip /bundles + +FROM nginx:stable + +COPY ./ngnix.conf /etc/nginx/conf.d/default.conf +COPY --from=build /bundles/ /var/www diff --git a/perftests/bundlesrv/ngnix.conf b/perftests/bundlesrv/ngnix.conf new file mode 100644 index 0000000..f0c3ae0 --- /dev/null +++ b/perftests/bundlesrv/ngnix.conf @@ -0,0 +1,10 @@ +server { + listen 80; + + root /var/www/; + autoindex on; + # Force all paths to load either itself (js files) or go through index.html. + location / { + try_files $uri /index.html; + } +} \ No newline at end of file diff --git a/perftests/bundlesrv/scenarios/build.sh b/perftests/bundlesrv/scenarios/build.sh new file mode 100755 index 0000000..8d151e8 --- /dev/null +++ b/perftests/bundlesrv/scenarios/build.sh @@ -0,0 +1,8 @@ + #!/bin/bash + + IFS=$'\n' + + for f in $(find . -mindepth 1 -maxdepth 1 -type d ); do + zip -x .* -x dist -r "$f" "$f/" + done + diff --git a/perftests/bundlesrv/scenarios/test1/default/eventgen.conf b/perftests/bundlesrv/scenarios/test1/default/eventgen.conf new file mode 100644 index 0000000..6fb3cb7 --- /dev/null +++ b/perftests/bundlesrv/scenarios/test1/default/eventgen.conf @@ -0,0 +1,14 @@ +[ciscoasa.sample] +sampleDir = samples +sampletype = raw +outputMode = tcpout +tcpDestinationHost = sc4s +tcpDestinationPort = 514 +end = 10 +mode = sample +interval = 1 +count = 100 +#2018-06-27T12:17:46 +token.0.token = \d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ +token.0.replacementType = timestamp +token.0.replacement = %Y-%m-%dT%H:%M:%SZ diff --git a/perftests/bundlesrv/scenarios/test1/samples/ciscoasa.sample b/perftests/bundlesrv/scenarios/test1/samples/ciscoasa.sample new file mode 100644 index 0000000..cd37166 --- /dev/null +++ b/perftests/bundlesrv/scenarios/test1/samples/ciscoasa.sample @@ -0,0 +1 @@ +<166>2018-06-27T12:17:46Z asa : %ASA-3-710003: TCP access denied by ACL from 179.236.133.160/8949 to outside:72.142.18.38/23 \ No newline at end of file diff --git a/perftests/bundlesrv/scenarios/test2/default/eventgen.conf b/perftests/bundlesrv/scenarios/test2/default/eventgen.conf new file mode 100644 index 0000000..98872e2 --- /dev/null +++ b/perftests/bundlesrv/scenarios/test2/default/eventgen.conf @@ -0,0 +1,13 @@ +[ciscoasa.sample] +sampleDir = samples +sampletype = raw +outputMode = tcpout +tcpDestinationHost = sc4s +tcpDestinationPort = 514 +end = 300 +mode = sample +interval = 1 +#2018-06-27T12:17:46 +token.0.token = \d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ +token.0.replacementType = timestamp +token.0.replacement = %Y-%m-%dT%H:%M:%SZ diff --git a/perftests/bundlesrv/scenarios/test2/samples/ciscoasa.sample b/perftests/bundlesrv/scenarios/test2/samples/ciscoasa.sample new file mode 100644 index 0000000..cd37166 --- /dev/null +++ b/perftests/bundlesrv/scenarios/test2/samples/ciscoasa.sample @@ -0,0 +1 @@ +<166>2018-06-27T12:17:46Z asa : %ASA-3-710003: TCP access denied by ACL from 179.236.133.160/8949 to outside:72.142.18.38/23 \ No newline at end of file diff --git a/test-with-compose.sh b/test-with-compose.sh index 400c3c8..3f08cbf 100755 --- a/test-with-compose.sh +++ b/test-with-compose.sh @@ -16,7 +16,7 @@ docker container create --name dummy \ docker cp tests/ dummy:/work/tests/ docker rm dummy -docker-compose build --build-arg RH_ACTIVATION=$RH_ACTIVATION --build-arg RH_ORG=$RH_ORG +docker-compose build docker-compose up --abort-on-container-exit --exit-code-from test docker container create --name dummy \ diff --git a/tests/conftest.py b/tests/conftest.py index cc16563..ab4fd96 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -39,7 +39,7 @@ def setup_splunk(): break except ConnectionRefusedError: tried += 1 - if tried > 180: + if tried > 600: raise sleep(1) return c diff --git a/tests/test_cisco_asa.py b/tests/test_cisco_asa.py index a908fc4..308356a 100644 --- a/tests/test_cisco_asa.py +++ b/tests/test_cisco_asa.py @@ -40,6 +40,7 @@ def test_cisco_asa_tradditional(record_property, setup_wordlist, setup_splunk): # <166>2018-06-27T12:17:46Z asa : %ASA-3-710003: TCP access denied by ACL from 179.236.133.160/8949 to outside:72.142.18.38/23 +@flaky(max_runs=3, min_passes=2) def test_cisco_asa_rfc5424(record_property, setup_wordlist, setup_splunk): host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) diff --git a/tests/test_cisco_ios.py b/tests/test_cisco_ios.py index 19746af..f729df9 100644 --- a/tests/test_cisco_ios.py +++ b/tests/test_cisco_ios.py @@ -5,7 +5,7 @@ # https://opensource.org/licenses/BSD-2-Clause from jinja2 import Environment -from jinja2 import Environment +from flaky import flaky from .sendmessage import * from .splunkutils import * @@ -14,6 +14,7 @@ # <190>30: foo: *Apr 29 13:58:46.411: %SYS-6-LOGGINGHOST_STARTSTOP: Logging to host 192.168.1.239 stopped - CLI initiated +@flaky(max_runs=3, min_passes=2) def test_cisco_ios(record_property, setup_wordlist, get_host_key, setup_splunk): host = get_host_key diff --git a/tests/test_fortinet_ngfw.py b/tests/test_fortinet_ngfw.py new file mode 100644 index 0000000..e7f982d --- /dev/null +++ b/tests/test_fortinet_ngfw.py @@ -0,0 +1,78 @@ +# Copyright 2019 Splunk, Inc. +# +# Use of this source code is governed by a BSD-2-clause-style +# license that can be found in the LICENSE-BSD2 file or at +# https://opensource.org/licenses/BSD-2-Clause +import random + +from flaky import flaky +from jinja2 import Environment + +from .sendmessage import * +from .splunkutils import * + +env = Environment(extensions=['jinja2_time.TimeExtension']) + +@flaky(max_runs=3, min_passes=2) +#<111> Aug 17 00:00:00 fortigate date=2015-08-11 time=19:19:43 devname=Nosey devid=FG800C3912801080 logid=0004000017 type=traffic subtype=sniffer level=notice vd=root srcip=fe80::20c:29ff:fe77:20d4 srcintf="port3" dstip=ff02::1:ff77:20d4 dstintf="port3" sessionid=408903 proto=58 action=accept policyid=2 dstcountry="Reserved" srccountry="Reserved" trandisp=snat transip=:: transport=0 service="icmp6/131/0" duration=36 sentbyte=0 rcvdbyte=40 sentpkt=0 rcvdpkt=0 appid=16321 app="IPv6.ICMP" appcat="Network.Service" apprisk=elevated applist="sniffer-profile" appact=detected utmaction=allow countapp=1 +def test_fortinet_fgt_event(record_property, setup_wordlist, setup_splunk): + host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) + + mt = env.from_string( + "{{ mark }}date={% now 'utc', '%Y-%m-%d' %} time={% now 'utc', '%H:%M:%S' %} devname={{ host }} devid=FGT60D4614044725 logid=0100040704 type=event subtype=system level=notice vd=root logdesc=\"System performance statistics\" action=\"perf-stats\" cpu=2 mem=35 totalsession=61 disk=2 bandwidth=158/138 setuprate=2 disklograte=0 fazlograte=0 msg=\"Performance statistics: average CPU: 2, memory: 35, concurrent sessions: 61, setup-rate: 2\"\n") + message = mt.render(mark="<13>", host=host) + + sendsingle(message) + + st = env.from_string("search index=main host=\"{{ host }}\" sourcetype=\"fgt_event\" | head 2") + search = st.render(host=host) + + resultCount, eventCount = splunk_single(setup_splunk, search) + + record_property("host", host) + record_property("resultCount", resultCount) + record_property("message", message) + + assert resultCount == 1 + +@flaky(max_runs=3, min_passes=2) +#<111> Aug 17 00:00:00 fortigate date=2015-08-11 time=19:19:43 devname=Nosey devid=FG800C3912801080 logid=0004000017 type=traffic subtype=sniffer level=notice vd=root srcip=fe80::20c:29ff:fe77:20d4 srcintf="port3" dstip=ff02::1:ff77:20d4 dstintf="port3" sessionid=408903 proto=58 action=accept policyid=2 dstcountry="Reserved" srccountry="Reserved" trandisp=snat transip=:: transport=0 service="icmp6/131/0" duration=36 sentbyte=0 rcvdbyte=40 sentpkt=0 rcvdpkt=0 appid=16321 app="IPv6.ICMP" appcat="Network.Service" apprisk=elevated applist="sniffer-profile" appact=detected utmaction=allow countapp=1 +def test_fortinet_fgt_traffic(record_property, setup_wordlist, setup_splunk): + host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) + + mt = env.from_string( + "{{ mark }}date={% now 'utc', '%Y-%m-%d' %} time={% now 'utc', '%H:%M:%S' %} devname={{ host }} devid=FG800C3912801080 logid=0004000017 type=traffic subtype=sniffer level=notice vd=root srcip=fe80::20c:29ff:fe77:20d4 srcintf=\"port3\" dstip=ff02::1:ff77:20d4 dstintf=\"port3\" sessionid=408903 proto=58 action=accept policyid=2 dstcountry=\"Reserved\" srccountry=\"Reserved\" trandisp=snat transip=:: transport=0 service=\"icmp6/131/0\" duration=36 sentbyte=0 rcvdbyte=40 sentpkt=0 rcvdpkt=0 appid=16321 app=\"IPv6.ICMP\" appcat=\"Network.Service\" apprisk=elevated applist=\"sniffer-profile\" appact=detected utmaction=allow countapp=1\n") + message = mt.render(mark="<13>", host=host) + sendsingle(message) + + st = env.from_string("search index=main host=\"{{ host }}\" sourcetype=\"fgt_traffic\" | head 2") + search = st.render(host=host) + + resultCount, eventCount = splunk_single(setup_splunk, search) + + record_property("host", host) + record_property("resultCount", resultCount) + record_property("message", message) + + assert resultCount == 1 + +@flaky(max_runs=3, min_passes=2) +#<111> Aug 17 00:00:00 fortigate date=2015-08-11 time=19:21:40 logver=52 devname=US-Corp_Main1 devid=FGT37D4613800138 logid=0317013312 type=utm subtype=webfilter eventtype=ftgd_allow level=notice vd=root sessionid=1490845588 user="" srcip=172.30.16.119 srcport=53235 srcintf="Internal" dstip=114.112.67.75 dstport=80 dstintf="External-SDC" proto=6 service=HTTP hostname="popo.wan.ijinshan.com" profile="scan" action=passthrough reqtype=direct url="/popo/launch?c=cHA9d29vZHMxOTgyQGhvdG1haWwuY29tJnV1aWQ9NDBiNDkyZDRmNzdhNjFmOTNlMjQwMjhiYjE3ZGRlYTYmY29tcGl" sentbyte=525 rcvdbyte=325 direction=outgoing msg="URL belongs to an allowed category in policy" method=domain cat=52 catdesc="Information Technology" +def test_fortinet_fgt_utm(record_property, setup_wordlist, setup_splunk): + host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) + + mt = env.from_string( + "{{ mark }}date={% now 'utc', '%Y-%m-%d' %} time={% now 'utc', '%H:%M:%S' %} devname={{ host }} devid=FGT37D4613800138 logid=0317013312 type=utm subtype=webfilter eventtype=ftgd_allow level=notice vd=root sessionid=1490845588 user=\"\" srcip=172.30.16.119 srcport=53235 srcintf=\"Internal\" dstip=114.112.67.75 dstport=80 dstintf=\"External-SDC\" proto=6 service=HTTP hostname=\"popo.wan.ijinshan.com\" profile=\"scan\" action=passthrough reqtype=direct url=\"/popo/launch?c=cHA9d29vZHMxOTgyQGhvdG1haWwuY29tJnV1aWQ9NDBiNDkyZDRmNzdhNjFmOTNlMjQwMjhiYjE3ZGRlYTYmY29tcGl\" sentbyte=525 rcvdbyte=325 direction=outgoing msg=\"URL belongs to an allowed category in policy\" method=domain cat=52 catdesc=\"Information Technology\"\n") + message = mt.render(mark="<13>", host=host) + sendsingle(message) + + st = env.from_string("search index=main host=\"{{ host }}\" sourcetype=\"fgt_utm\" | head 2") + search = st.render(host=host) + + resultCount, eventCount = splunk_single(setup_splunk, search) + + record_property("host", host) + record_property("resultCount", resultCount) + record_property("message", message) + + assert resultCount == 1 diff --git a/tests/test_palo_alto.py b/tests/test_palo_alto.py index ec8744e..5a601f0 100644 --- a/tests/test_palo_alto.py +++ b/tests/test_palo_alto.py @@ -14,7 +14,7 @@ env = Environment(extensions=['jinja2_time.TimeExtension']) -# <190>Jan 28 01:28:35 PA-VM300-goran1 1,2014/01/28 01:28:35,007200001056,TRAFFIC,end,1,2014/01/28 01:28:34,192.168.41.30,192.168.41.255,10.193.16.193,192.168.41.255,allow-all,,,netbios-ns,vsys1,Trust,Untrust,ethernet1/1,ethernet1/2,To-Panorama,2014/01/28 01:28:34,8720,1,137,137,11637,137,0x400000,udp,allow,276,276,0,3,2014/01/28 01:28:02,2,any,0,2076326,0x0,192.168.0.0-192.168.255.255,192.168.0.0-192.168.255.255,0,3,0 +#<190>Jan 28 01:28:35 PA-VM300-goran1 1,2014/01/28 01:28:35,007200001056,TRAFFIC,end,1,2014/01/28 01:28:34,192.168.41.30,192.168.41.255,10.193.16.193,192.168.41.255,allow-all,,,netbios-ns,vsys1,Trust,Untrust,ethernet1/1,ethernet1/2,To-Panorama,2014/01/28 01:28:34,8720,1,137,137,11637,137,0x400000,udp,allow,276,276,0,3,2014/01/28 01:28:02,2,any,0,2076326,0x0,192.168.0.0-192.168.255.255,192.168.0.0-192.168.255.255,0,3,0 @flaky(max_runs=3, min_passes=2) def test_palo_alto_traffic(record_property, setup_wordlist, setup_splunk): host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist))