From 5c885dc7f4521ad47a43a79a01db78027084e184 Mon Sep 17 00:00:00 2001 From: Ryan Faircloth <35384120+rfaircloth-splunk@users.noreply.github.com> Date: Mon, 15 Jul 2019 11:33:51 -0500 Subject: [PATCH] Feature/filter cisco ios (#21) * Support Cisco ASA and misc fixes Fixes #14 Fixes #15 Fixes #16 * Test Refactor Fixes #18 Fixes #19 * New filter cisco IOS Fixes #20 * Update .env.template --- .env.template | 3 + .../filters/cisco_asa_tradditional.conf | 2 +- package/etc/conf.d/filters/cisco_ios.conf | 16 + package/etc/context/splunk_index.csv | 2 + tests/__init__.py | 5 + tests/conftest.py | 45 + tests/data/wordlist.txt | 1633 +++++++++++++++++ tests/sendmessage.py | 26 + tests/splunkutils.py | 37 + tests/test_cisco_asa.py | 61 + tests/test_cisco_ios.py | 35 + tests/test_palo_alto.py | 60 + tests/test_poc.py | 174 +- 13 files changed, 1931 insertions(+), 168 deletions(-) create mode 100644 package/etc/conf.d/filters/cisco_ios.conf create mode 100644 tests/__init__.py create mode 100644 tests/conftest.py create mode 100644 tests/data/wordlist.txt create mode 100644 tests/sendmessage.py create mode 100644 tests/splunkutils.py create mode 100644 tests/test_cisco_asa.py create mode 100644 tests/test_cisco_ios.py create mode 100644 tests/test_palo_alto.py diff --git a/.env.template b/.env.template index b828de9..b7294ec 100644 --- a/.env.template +++ b/.env.template @@ -16,3 +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 +SPLUNKBASE_USERNAME=username +SPLUNKBASE_PASSWORD=password \ No newline at end of file diff --git a/package/etc/conf.d/filters/cisco_asa_tradditional.conf b/package/etc/conf.d/filters/cisco_asa_tradditional.conf index 6ed4f89..a912baf 100644 --- a/package/etc/conf.d/filters/cisco_asa_tradditional.conf +++ b/package/etc/conf.d/filters/cisco_asa_tradditional.conf @@ -5,7 +5,7 @@ log { or message('^.{10,60} : %ASA-\d+-\d{1,10}: ') ;}; - #Cisco ASA can send 3164 or 5424 either way we are good with basic parsing + #Cisco ASA can send 3264 or 5424 either way we are good with basic parsing parser { #basic parsing syslog-parser(time-zone(`default-timezone`)); diff --git a/package/etc/conf.d/filters/cisco_ios.conf b/package/etc/conf.d/filters/cisco_ios.conf new file mode 100644 index 0000000..98427f1 --- /dev/null +++ b/package/etc/conf.d/filters/cisco_ios.conf @@ -0,0 +1,16 @@ +# =============================================================================================== +# Cisco IOS (Route/Switch) +# =============================================================================================== + +log { + + source(s_default-ports); + + parser { cisco-parser(); }; + + parser {p_add_context_splunk(key("cisco:ios")); }; + rewrite { r_set_splunk_basic(template("t_msg_only"))}; #--HEC-- + destination(d_hec); #--HEC-- + + flags(final); +}; diff --git a/package/etc/context/splunk_index.csv b/package/etc/context/splunk_index.csv index cb1760e..75b98d6 100644 --- a/package/etc/context/splunk_index.csv +++ b/package/etc/context/splunk_index.csv @@ -1,5 +1,7 @@ cisco:asa,index,main cisco:asa,sourcetype,cisco:asa +cisco:ios,index,main +cisco:ios,sourcetype,cisco:ios pan:traffic,index,main pan:threat,index,main pan:system,index,main diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..4913c30 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,5 @@ +# 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 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..cc16563 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,45 @@ +# 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 os +import random +from time import sleep + +import pytest +import splunklib.client as client + + +@pytest.fixture(scope="module") +def setup_wordlist(): + path_to_current_file = os.path.realpath(__file__) + current_directory = os.path.split(path_to_current_file)[0] + path_to_file = os.path.join(current_directory, "data/wordlist.txt") + + wordlist = [line.rstrip('\n') for line in open(path_to_file)] + return wordlist + + +@pytest.fixture +def get_host_key(setup_wordlist): + part1 = random.choice(setup_wordlist) + part2 = random.choice(setup_wordlist) + host = "{}-{}".format(part1, part2) + + return host + + +@pytest.fixture +def setup_splunk(): + tried = 0 + while True: + try: + c = client.connect(username="admin", password="Changed@11", host="splunk", port="8089") + break + except ConnectionRefusedError: + tried += 1 + if tried > 180: + raise + sleep(1) + return c diff --git a/tests/data/wordlist.txt b/tests/data/wordlist.txt new file mode 100644 index 0000000..d6a73fe --- /dev/null +++ b/tests/data/wordlist.txt @@ -0,0 +1,1633 @@ +acrobat +africa +alaska +albert +albino +album +alcohol +alex +alpha +amadeus +amanda +amazon +america +analog +animal +antenna +antonio +apollo +april +aroma +artist +aspirin +athlete +atlas +banana +bandit +banjo +bikini +bingo +bonus +camera +canada +carbon +casino +catalog +cinema +citizen +cobra +comet +compact +complex +context +credit +critic +crystal +culture +david +delta +dialog +diploma +doctor +domino +dragon +drama +extra +fabric +final +focus +forum +galaxy +gallery +global +harmony +hotel +humor +index +japan +kilo +lemon +liter +lotus +mango +melon +menu +meter +metro +mineral +model +music +object +piano +pirate +plastic +radio +report +signal +sport +studio +subject +super +tango +taxi +tempo +tennis +textile +tokyo +total +tourist +video +visa +academy +alfred +atlanta +atomic +barbara +bazaar +brother +budget +cabaret +cadet +candle +capsule +caviar +channel +chapter +circle +cobalt +comrade +condor +crimson +cyclone +darwin +declare +denver +desert +divide +dolby +domain +double +eagle +echo +eclipse +editor +educate +edward +effect +electra +emerald +emotion +empire +eternal +evening +exhibit +expand +explore +extreme +ferrari +forget +freedom +friday +fuji +galileo +genesis +gravity +habitat +hamlet +harlem +helium +holiday +hunter +ibiza +iceberg +imagine +infant +isotope +jackson +jamaica +jasmine +java +jessica +kitchen +lazarus +letter +license +lithium +loyal +lucky +magenta +manual +marble +maxwell +mayor +monarch +monday +money +morning +mother +mystery +native +nectar +nelson +network +nikita +nobel +nobody +nominal +norway +nothing +number +october +office +oliver +opinion +option +order +outside +package +pandora +panther +papa +pattern +pedro +pencil +people +phantom +philips +pioneer +pluto +podium +portal +potato +process +proxy +pupil +python +quality +quarter +quiet +rabbit +radical +radius +rainbow +ramirez +ravioli +raymond +respect +respond +result +resume +richard +river +roger +roman +rondo +sabrina +salary +salsa +sample +samuel +saturn +savage +scarlet +scorpio +sector +serpent +shampoo +sharon +silence +simple +society +sonar +sonata +soprano +sparta +spider +sponsor +abraham +action +active +actor +adam +address +admiral +adrian +agenda +agent +airline +airport +alabama +aladdin +alarm +algebra +alibi +alice +alien +almond +alpine +amber +amigo +ammonia +analyze +anatomy +angel +annual +answer +apple +archive +arctic +arena +arizona +armada +arnold +arsenal +arthur +asia +aspect +athena +audio +august +austria +avenue +average +axiom +aztec +bagel +baker +balance +ballad +ballet +bambino +bamboo +baron +basic +basket +battery +belgium +benefit +berlin +bermuda +bernard +bicycle +binary +biology +bishop +blitz +block +blonde +bonjour +boris +boston +bottle +boxer +brandy +bravo +brazil +bridge +british +bronze +brown +bruce +bruno +brush +burger +burma +cabinet +cactus +cafe +cairo +calypso +camel +campus +canal +cannon +canoe +cantina +canvas +canyon +capital +caramel +caravan +career +cargo +carlo +carol +carpet +cartel +cartoon +castle +castro +cecilia +cement +center +century +ceramic +chamber +chance +change +chaos +charlie +charm +charter +cheese +chef +chemist +cherry +chess +chicago +chicken +chief +china +cigar +circus +city +clara +classic +claudia +clean +client +climax +clinic +clock +club +cockpit +coconut +cola +collect +colombo +colony +color +combat +comedy +command +company +concert +connect +consul +contact +contour +control +convert +copy +corner +corona +correct +cosmos +couple +courage +cowboy +craft +crash +cricket +crown +cuba +dallas +dance +daniel +decade +decimal +degree +delete +deliver +delphi +deluxe +demand +demo +denmark +derby +design +detect +develop +diagram +diamond +diana +diego +diesel +diet +digital +dilemma +direct +disco +disney +distant +dollar +dolphin +donald +drink +driver +dublin +duet +dynamic +earth +east +ecology +economy +edgar +egypt +elastic +elegant +element +elite +elvis +email +empty +energy +engine +english +episode +equator +escape +escort +ethnic +europe +everest +evident +exact +example +exit +exotic +export +express +factor +falcon +family +fantasy +fashion +fiber +fiction +fidel +fiesta +figure +film +filter +finance +finish +finland +first +flag +flash +florida +flower +fluid +flute +folio +ford +forest +formal +formula +fortune +forward +fragile +france +frank +fresh +friend +frozen +future +gabriel +gamma +garage +garcia +garden +garlic +gemini +general +genetic +genius +germany +gloria +gold +golf +gondola +gong +good +gordon +gorilla +grand +granite +graph +green +group +guide +guitar +guru +hand +happy +harbor +harvard +havana +hawaii +helena +hello +henry +hilton +history +horizon +house +human +icon +idea +igloo +igor +image +impact +import +india +indigo +input +insect +instant +iris +italian +jacket +jacob +jaguar +janet +jargon +jazz +jeep +john +joker +jordan +judo +jumbo +june +jungle +junior +jupiter +karate +karma +kayak +kermit +king +koala +korea +labor +lady +lagoon +laptop +laser +latin +lava +lecture +left +legal +level +lexicon +liberal +libra +lily +limbo +limit +linda +linear +lion +liquid +little +llama +lobby +lobster +local +logic +logo +lola +london +lucas +lunar +machine +macro +madam +madonna +madrid +maestro +magic +magnet +magnum +mailbox +major +mama +mambo +manager +manila +marco +marina +market +mars +martin +marvin +mary +master +matrix +maximum +media +medical +mega +melody +memo +mental +mentor +mercury +message +metal +meteor +method +mexico +miami +micro +milk +million +minimum +minus +minute +miracle +mirage +miranda +mister +mixer +mobile +modem +modern +modular +moment +monaco +monica +monitor +mono +monster +montana +morgan +motel +motif +motor +mozart +multi +museum +mustang +natural +neon +nepal +neptune +nerve +neutral +nevada +news +next +ninja +nirvana +normal +nova +novel +nuclear +numeric +nylon +oasis +observe +ocean +octopus +olivia +olympic +omega +opera +optic +optimal +orange +orbit +organic +orient +origin +orlando +oscar +oxford +oxygen +ozone +pablo +pacific +pagoda +palace +pamela +panama +pancake +panda +panel +panic +paradox +pardon +paris +parker +parking +parody +partner +passage +passive +pasta +pastel +patent +patient +patriot +patrol +pegasus +pelican +penguin +pepper +percent +perfect +perfume +period +permit +person +peru +phone +photo +picasso +picnic +picture +pigment +pilgrim +pilot +pixel +pizza +planet +plasma +plaza +pocket +poem +poetic +poker +polaris +police +politic +polo +polygon +pony +popcorn +popular +postage +precise +prefix +premium +present +price +prince +printer +prism +private +prize +product +profile +program +project +protect +proton +public +pulse +puma +pump +pyramid +queen +radar +ralph +random +rapid +rebel +record +recycle +reflex +reform +regard +regular +relax +reptile +reverse +ricardo +right +ringo +risk +ritual +robert +robot +rocket +rodeo +romeo +royal +russian +safari +salad +salami +salmon +salon +salute +samba +sandra +santana +sardine +school +scoop +scratch +screen +script +scroll +second +secret +section +segment +select +seminar +senator +senior +sensor +serial +service +shadow +sharp +sheriff +shock +short +shrink +sierra +silicon +silk +silver +similar +simon +single +siren +slang +slogan +smart +smoke +snake +social +soda +solar +solid +solo +sonic +source +soviet +special +speed +sphere +spiral +spirit +spring +static +status +stereo +stone +stop +street +strong +student +style +sultan +susan +sushi +suzuki +switch +symbol +system +tactic +tahiti +talent +tarzan +telex +texas +theory +thermos +tiger +titanic +tomato +topic +tornado +toronto +torpedo +totem +tractor +traffic +transit +trapeze +travel +tribal +trick +trident +trilogy +tripod +tropic +trumpet +tulip +tuna +turbo +twist +ultra +uniform +union +uranium +vacuum +valid +vampire +vanilla +vatican +velvet +ventura +venus +vertigo +veteran +victor +vienna +viking +village +vincent +violet +violin +virtual +virus +vision +visitor +visual +vitamin +viva +vocal +vodka +volcano +voltage +volume +voyage +water +weekend +welcome +western +window +winter +wizard +wolf +world +xray +yankee +yoga +yogurt +yoyo +zebra +zero +zigzag +zipper +zodiac +zoom +acid +adios +agatha +alamo +alert +almanac +aloha +andrea +anita +arcade +aurora +avalon +baby +baggage +balloon +bank +basil +begin +biscuit +blue +bombay +botanic +brain +brenda +brigade +cable +calibre +carmen +cello +celtic +chariot +chrome +citrus +civil +cloud +combine +common +cool +copper +coral +crater +cubic +cupid +cycle +depend +door +dream +dynasty +edison +edition +enigma +equal +eric +event +evita +exodus +extend +famous +farmer +food +fossil +frog +fruit +geneva +gentle +george +giant +gilbert +gossip +gram +greek +grille +hammer +harvest +hazard +heaven +herbert +heroic +hexagon +husband +immune +inca +inch +initial +isabel +ivory +jason +jerome +joel +joshua +journal +judge +juliet +jump +justice +kimono +kinetic +leonid +leopard +lima +maze +medusa +member +memphis +michael +miguel +milan +mile +miller +mimic +mimosa +mission +monkey +moral +moses +mouse +nancy +natasha +nebula +nickel +nina +noise +orchid +oregano +origami +orinoco +orion +othello +paper +paprika +prelude +prepare +pretend +promise +prosper +provide +puzzle +remote +repair +reply +rival +riviera +robin +rose +rover +rudolf +saga +sahara +scholar +shelter +ship +shoe +sigma +sister +sleep +smile +spain +spark +split +spray +square +stadium +star +storm +story +strange +stretch +stuart +subway +sugar +sulfur +summer +survive +sweet +swim +table +taboo +target +teacher +telecom +temple +tibet +ticket +tina +today +toga +tommy +tower +trivial +tunnel +turtle +twin +uncle +unicorn +unique +update +valery +vega +version +voodoo +warning +william +wonder +year +yellow +young +absent +absorb +absurd +accent +alfonso +alias +ambient +anagram +andy +anvil +appear +apropos +archer +ariel +armor +arrow +austin +avatar +axis +baboon +bahama +bali +balsa +barcode +bazooka +beach +beast +beatles +beauty +before +benny +betty +between +beyond +billy +bison +blast +bless +bogart +bonanza +book +border +brave +bread +break +broken +bucket +buenos +buffalo +bundle +button +buzzer +byte +caesar +camilla +canary +candid +carrot +cave +chant +child +choice +chris +cipher +clarion +clark +clever +cliff +clone +conan +conduct +congo +costume +cotton +cover +crack +current +danube +data +decide +deposit +desire +detail +dexter +dinner +donor +druid +drum +easy +eddie +enjoy +enrico +epoxy +erosion +except +exile +explain +fame +fast +father +felix +field +fiona +fire +fish +flame +flex +flipper +float +flood +floor +forbid +forever +fractal +frame +freddie +front +fuel +gallop +game +garbo +gate +gelatin +gibson +ginger +giraffe +gizmo +glass +goblin +gopher +grace +gray +gregory +grid +griffin +ground +guest +gustav +gyro +hair +halt +harris +heart +heavy +herman +hippie +hobby +honey +hope +horse +hostel +hydro +imitate +info +ingrid +inside +invent +invest +invite +ivan +james +jester +jimmy +join +joseph +juice +julius +july +kansas +karl +kevin +kiwi +ladder +lake +laura +learn +legacy +legend +lesson +life +light +list +locate +lopez +lorenzo +love +lunch +malta +mammal +margin +margo +marion +mask +match +mayday +meaning +mercy +middle +mike +mirror +modest +morph +morris +mystic +nadia +nato +navy +needle +neuron +never +newton +nice +night +nissan +nitro +nixon +north +oberon +octavia +ohio +olga +open +opus +orca +oval +owner +page +paint +palma +parent +parlor +parole +paul +peace +pearl +perform +phoenix +phrase +pierre +pinball +place +plate +plato +plume +pogo +point +polka +poncho +powder +prague +press +presto +pretty +prime +promo +quest +quick +quiz +quota +race +rachel +raja +ranger +region +remark +rent +reward +rhino +ribbon +rider +road +rodent +round +rubber +ruby +rufus +sabine +saddle +sailor +saint +salt +scale +scuba +season +secure +shake +shallow +shannon +shave +shelf +sherman +shine +shirt +side +sinatra +sincere +size +slalom +slow +small +snow +sofia +song +sound +south +speech +spell +spend +spoon +stage +stamp +stand +state +stella +stick +sting +stock +store +sunday +sunset +support +supreme +sweden +swing +tape +tavern +think +thomas +tictac +time +toast +tobacco +tonight +torch +torso +touch +toyota +trade +tribune +trinity +triton +truck +trust +type +under +unit +urban +urgent +user +value +vendor +venice +verona +vibrate +virgo +visible +vista +vital +voice +vortex +waiter +watch +wave +weather +wedding +wheel +whiskey +wisdom +android +annex +armani +cake +confide +deal +define +dispute +genuine +idiom +impress +include +ironic +null +nurse +obscure +prefer +prodigy +ego +fax +jet +job +rio +ski +yes \ No newline at end of file diff --git a/tests/sendmessage.py b/tests/sendmessage.py new file mode 100644 index 0000000..6388c78 --- /dev/null +++ b/tests/sendmessage.py @@ -0,0 +1,26 @@ +# 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 socket +from time import sleep + + +def sendsingle(message): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server_address = ('sc4s', 514) + + tried = 0 + while True: + try: + sock.connect(server_address) + break + except socket: + tried += 1 + if tried > 90: + raise + sleep(1) + sock.sendall(str.encode(message)) + sock.close() diff --git a/tests/splunkutils.py b/tests/splunkutils.py new file mode 100644 index 0000000..7227ae9 --- /dev/null +++ b/tests/splunkutils.py @@ -0,0 +1,37 @@ +# 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 +from time import sleep + + +def splunk_single(service, search): + kwargs_normalsearch = {"exec_mode": "normal"} + tried = 0 + while True: + job = service.jobs.create(search, **kwargs_normalsearch) + + # A normal search returns the job's SID right away, so we need to poll for completion + while True: + while not job.is_ready(): + pass + stats = {"isDone": job["isDone"], + "doneProgress": float(job["doneProgress"]) * 100, + "scanCount": int(job["scanCount"]), + "eventCount": int(job["eventCount"]), + "resultCount": int(job["resultCount"])} + + if stats["isDone"] == "1": + break + sleep(2) + + # Get the results and display them + resultCount = stats["resultCount"] + eventCount = stats["eventCount"] + if resultCount > 0 or tried > 15: + break + else: + tried += 1 + sleep(1) + return resultCount, eventCount diff --git a/tests/test_cisco_asa.py b/tests/test_cisco_asa.py new file mode 100644 index 0000000..a908fc4 --- /dev/null +++ b/tests/test_cisco_asa.py @@ -0,0 +1,61 @@ +# 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']) + + +# Apr 15 2017 00:21:14 192.168.12.1 : %ASA-5-111010: User 'john', running 'CLI' from IP 0.0.0.0, executed 'dir disk0:/dap.xml' +# Apr 15 2017 00:22:27 192.168.12.1 : %ASA-4-313005: No matching connection for ICMP error message: icmp src outside:81.24.28.226 dst inside:72.142.17.10 (type 3, code 0) on outside interface. Original IP payload: udp src 72.142.17.10/40998 dst 194.153.237.66/53. +# Apr 15 2017 00:22:42 192.168.12.1 : %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_tradditional(record_property, setup_wordlist, setup_splunk): + host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) + + mt = env.from_string( + "{{ mark }} {% now 'utc', '%b %d %H:%M:%S' %} {{ host }} : %ASA-3-710003: TCP access denied by ACL from 179.236.133.160/3624 to outside:72.142.18.38/23\n") + message = mt.render(mark="<111>", host=host) + + sendsingle(message) + + st = env.from_string("search index=main host=\"{{ host }}\" sourcetype=\"cisco:asa\" | 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 + + +# <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 +def test_cisco_asa_rfc5424(record_property, setup_wordlist, setup_splunk): + host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) + + mt = env.from_string( + "{{ mark }} {% now 'utc', '%Y-%m-%dT%H:%M:%SZ' %} {{ host }} : %ASA-3-710003: TCP access denied by ACL from 179.236.133.160/5424 to outside:72.142.18.38/23\n") + message = mt.render(mark="<166>", host=host) + + sendsingle(message) + + st = env.from_string("search index=main host=\"{{ host }}\" sourcetype=\"cisco:asa\" | 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_cisco_ios.py b/tests/test_cisco_ios.py new file mode 100644 index 0000000..19746af --- /dev/null +++ b/tests/test_cisco_ios.py @@ -0,0 +1,35 @@ +# 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 + +from jinja2 import Environment +from jinja2 import Environment + +from .sendmessage import * +from .splunkutils import * + +env = Environment(extensions=['jinja2_time.TimeExtension']) + + +# <190>30: foo: *Apr 29 13:58:46.411: %SYS-6-LOGGINGHOST_STARTSTOP: Logging to host 192.168.1.239 stopped - CLI initiated +def test_cisco_ios(record_property, setup_wordlist, get_host_key, setup_splunk): + host = get_host_key + + mt = env.from_string( + "{{ mark }}{{ seq }}: {{ host }}: *{% now 'utc', '%b %d %H:%M:%S' %}.100: CET: %SEC-6-IPACCESSLOGP: list 110 denied tcp 54.122.123.124(8932) -> 10.1.0.1(22), 1 packet\n") + message = mt.render(mark="<166>", seq=20, host=host) + + sendsingle(message) + + st = env.from_string("search index=main host=\"{{ host }}\" sourcetype=\"cisco:ios\" | 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 new file mode 100644 index 0000000..ec8744e --- /dev/null +++ b/tests/test_palo_alto.py @@ -0,0 +1,60 @@ +# 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']) + + +# <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)) + + mt = env.from_string( + "{{ mark }} {% now 'utc', '%b %d %H:%M:%S' %} {{ host }} 1,{% now 'utc', '%Y/%m/%d %H:%M:%S' %},007200001056,TRAFFIC,end,1,{% now 'utc', '%Y/%m/%d %H:%M:%S' %},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\n") + message = mt.render(mark="<111>", host=host) + + sendsingle(message) + + st = env.from_string("search index=main host=\"{{ host }}\" sourcetype=\"pan: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 + + +# <190>Oct 30 09:46:17 1,2012/10/30 09:46:17,01606001116,THREAT,url,1,2012/04/10 04:39:55,192.168.0.2,204.232.231.46,0.0.0.0,0.0.0.0,rule1,crusher,,web-browsing,vsys1,trust,untrust,ethernet1/2,ethernet1/1,forwardAll,2012/04/10 04:39:57,22860,1,59303,80,0,0,0x208000,tcp,alert,"litetopdetect.cn/index.php",(9999),not-resolved,informational,client-to-server,0,0x0,192.168.0.0-192.168.255.255,United States,0,text/html +@flaky(max_runs=3, min_passes=2) +def test_palo_alto_threat(record_property, setup_wordlist, setup_splunk): + host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) + + mt = env.from_string( + "{{ mark }} {% now 'utc', '%b %d %H:%M:%S' %} {{ host }} 1,{% now 'utc', '%Y/%m/%d %H:%M:%S' %},01606001116,THREAT,url,1,{% now 'utc', '%Y/%m/%d %H:%M:%S' %},192.168.0.2,204.232.231.46,0.0.0.0,0.0.0.0,rule1,crusher,,web-browsing,vsys1,trust,untrust,ethernet1/2,ethernet1/1,forwardAll,2012/04/10 04:39:57,22860,1,59303,80,0,0,0x208000,tcp,alert,\"litetopdetect.cn/index.php\",(9999),not-resolved,informational,client-to-server,0,0x0,192.168.0.0-192.168.255.255,United States,0,text/html\n") + message = mt.render(mark="<111>", host=host) + + sendsingle(message) + + st = env.from_string("search index=main host=\"{{ host }}\" sourcetype=\"pan:threat\" | 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_poc.py b/tests/test_poc.py index 1a45e87..37dcdef 100644 --- a/tests/test_poc.py +++ b/tests/test_poc.py @@ -1,91 +1,17 @@ -#Copyright 2019 Splunk, Inc. +# 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 +# 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 -import socket -import urllib.request -from time import sleep -import pytest from flaky import flaky -import splunklib.client as client from jinja2 import Environment -env = Environment(extensions=['jinja2_time.TimeExtension']) - - -@pytest.fixture -def setup_wordlist(): - word_url = "http://svnweb.freebsd.org/csrg/share/dict/words?view=co&content-type=text/plain" - response = urllib.request.urlopen(word_url) - long_txt = response.read().decode() - return long_txt.splitlines() - - -@pytest.fixture -def setup_splunk(): - tried = 0 - while True: - try: - c = client.connect(username="admin", password="Changed@11", host="splunk", port="8089") - break - except ConnectionRefusedError: - tried += 1 - if tried > 180: - raise - sleep(1) - return c - - -def sendsingle(message): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - server_address = ('sc4s', 514) - - tried = 0 - while True: - try: - sock.connect(server_address) - break - except socket: - tried += 1 - if tried > 90: - raise - sleep(1) - sock.sendall(str.encode(message)) - sock.close() - - -def splunk_single(service, search): - kwargs_normalsearch = {"exec_mode": "normal"} - tried = 0 - while True: - job = service.jobs.create(search, **kwargs_normalsearch) +from .sendmessage import * +from .splunkutils import * - # A normal search returns the job's SID right away, so we need to poll for completion - while True: - while not job.is_ready(): - pass - stats = {"isDone": job["isDone"], - "doneProgress": float(job["doneProgress"]) * 100, - "scanCount": int(job["scanCount"]), - "eventCount": int(job["eventCount"]), - "resultCount": int(job["resultCount"])} - - if stats["isDone"] == "1": - break - sleep(2) - - # Get the results and display them - resultCount = stats["resultCount"] - eventCount = stats["eventCount"] - if resultCount > 0 or tried > 15: - break - else: - tried += 1 - sleep(1) - return resultCount, eventCount +env = Environment(extensions=['jinja2_time.TimeExtension']) @flaky(max_runs=3, min_passes=2) @@ -107,89 +33,3 @@ def test_defaultroute(record_property, setup_wordlist, setup_splunk): record_property("message", message) assert resultCount == 1 - -#<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)) - - mt = env.from_string("{{ mark }} {% now 'utc', '%b %d %H:%M:%S' %} {{ host }} 1,{% now 'utc', '%Y/%m/%d %H:%M:%S' %},007200001056,TRAFFIC,end,1,{% now 'utc', '%Y/%m/%d %H:%M:%S' %},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\n") - message = mt.render(mark="<111>", host=host) - - sendsingle(message) - - st = env.from_string("search index=main host=\"{{ host }}\" sourcetype=\"pan: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 - -#<190>Oct 30 09:46:17 1,2012/10/30 09:46:17,01606001116,THREAT,url,1,2012/04/10 04:39:55,192.168.0.2,204.232.231.46,0.0.0.0,0.0.0.0,rule1,crusher,,web-browsing,vsys1,trust,untrust,ethernet1/2,ethernet1/1,forwardAll,2012/04/10 04:39:57,22860,1,59303,80,0,0,0x208000,tcp,alert,"litetopdetect.cn/index.php",(9999),not-resolved,informational,client-to-server,0,0x0,192.168.0.0-192.168.255.255,United States,0,text/html -@flaky(max_runs=3, min_passes=2) -def test_palo_alto_threat(record_property, setup_wordlist, setup_splunk): - host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) - - mt = env.from_string("{{ mark }} {% now 'utc', '%b %d %H:%M:%S' %} {{ host }} 1,{% now 'utc', '%Y/%m/%d %H:%M:%S' %},01606001116,THREAT,url,1,{% now 'utc', '%Y/%m/%d %H:%M:%S' %},192.168.0.2,204.232.231.46,0.0.0.0,0.0.0.0,rule1,crusher,,web-browsing,vsys1,trust,untrust,ethernet1/2,ethernet1/1,forwardAll,2012/04/10 04:39:57,22860,1,59303,80,0,0,0x208000,tcp,alert,\"litetopdetect.cn/index.php\",(9999),not-resolved,informational,client-to-server,0,0x0,192.168.0.0-192.168.255.255,United States,0,text/html\n") - message = mt.render(mark="<111>", host=host) - - sendsingle(message) - - st = env.from_string("search index=main host=\"{{ host }}\" sourcetype=\"pan:threat\" | 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 - -#Apr 15 2017 00:21:14 192.168.12.1 : %ASA-5-111010: User 'john', running 'CLI' from IP 0.0.0.0, executed 'dir disk0:/dap.xml' -#Apr 15 2017 00:22:27 192.168.12.1 : %ASA-4-313005: No matching connection for ICMP error message: icmp src outside:81.24.28.226 dst inside:72.142.17.10 (type 3, code 0) on outside interface. Original IP payload: udp src 72.142.17.10/40998 dst 194.153.237.66/53. -#Apr 15 2017 00:22:42 192.168.12.1 : %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_tradditional(record_property, setup_wordlist, setup_splunk): - host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) - - mt = env.from_string("{{ mark }} {% now 'utc', '%b %d %H:%M:%S' %} {{ host }} : %ASA-3-710003: TCP access denied by ACL from 179.236.133.160/3624 to outside:72.142.18.38/23\n") - message = mt.render(mark="<111>", host=host) - - sendsingle(message) - - st = env.from_string("search index=main host=\"{{ host }}\" sourcetype=\"cisco:asa\" | 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 - -#<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 -def test_cisco_asa_rfc5424(record_property, setup_wordlist, setup_splunk): - host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist)) - - mt = env.from_string("{{ mark }} {% now 'utc', '%Y-%m-%dT%H:%M:%SZ' %} {{ host }} : %ASA-3-710003: TCP access denied by ACL from 179.236.133.160/5424 to outside:72.142.18.38/23\n") - message = mt.render(mark="<166>", host=host) - - sendsingle(message) - - st = env.from_string("search index=main host=\"{{ host }}\" sourcetype=\"cisco:asa\" | 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 -