Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ There are 2 extra functions for special lookups in the Valhalla database (for cu

## Demo Access

> Important: The demo API key is not available and demo access is not possible anymore. Hence, the following section and everything regarding the given demo API key is outdated.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this too broad?

The demo key is still very much supported and working; only the access to the rule info endpoint has been disabled for the demo key.

Same for changes below.


There is a demo API key that can be used for testing purposes.

```
Expand Down
83 changes: 47 additions & 36 deletions tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

from valhallaAPI.valhalla import ValhallaAPI

DEMO_KEY = "1111111111111111111111111111111111111111111111111111111111111111"
# Demo key is deprecated, but still works for testing purposes
DEPRECATED_DEMO_KEY = "1111111111111111111111111111111111111111111111111111111111111111"
INVALID_KEY = "invalid"
RULES_TEXT = "VALHALLA YARA RULE SET"
RULE_INFO_TEST = "Casing_Anomaly_ByPass" # Only rule info allowed for DEMO user
Expand All @@ -26,7 +27,7 @@ def test_status():
Retrieves the API status
:return:
"""
v = ValhallaAPI(api_key=DEMO_KEY)
v = ValhallaAPI(api_key=DEPRECATED_DEMO_KEY)
status = v.get_status()
assert status["status"] == "green"

Expand All @@ -36,9 +37,8 @@ def test_subscription():
Retrieves the subscription status of the current user
:return:
"""
v = ValhallaAPI()
v = ValhallaAPI(api_key=DEPRECATED_DEMO_KEY)
response = v.get_subscription()
print(response)
assert len(response) == 5
assert response["subscription"] == "limited"
assert response["tags"] == ['DEMO']
Expand All @@ -49,7 +49,7 @@ def test_demo_rules_json():
Retrieves the demo rules from the rule feed
:return:
"""
v = ValhallaAPI(api_key=DEMO_KEY)
v = ValhallaAPI(api_key=DEPRECATED_DEMO_KEY)
rules_response = v.get_rules_json()
assert len(rules_response['rules']) > 0

Expand All @@ -59,20 +59,19 @@ def test_demo_rule_info():
Retrieves the demo rule info
:return:
"""
v = ValhallaAPI(api_key=DEMO_KEY)
v = ValhallaAPI(api_key=DEPRECATED_DEMO_KEY)
rules_response1 = v.get_rule_info(RULE_INFO_DISALLOWED)
assert 'rule_matches' not in rules_response1
rules_response2 = v.get_rule_info(RULE_INFO_TEST)
assert 'rule_matches' in rules_response2
assert len(rules_response2['rule_matches']) > 0
assert 'rule_matches' not in rules_response2


def test_demo_rules_product_limited():
"""
Retrieves the demo rules from the rule feed with a product set
:return:
"""
v = ValhallaAPI(api_key=DEMO_KEY)
v = ValhallaAPI(api_key=DEPRECATED_DEMO_KEY)
rules_response = v.get_rules_json()
rules_response_limited = v.get_rules_json(product="DummyTest")
assert len(rules_response['rules']) > 0
Expand All @@ -86,7 +85,7 @@ def test_demo_rules_custom_limited():
Retrieves the demo rules from the rule feed with custom expressions
:return:
"""
v = ValhallaAPI(api_key=DEMO_KEY)
v = ValhallaAPI(api_key=DEPRECATED_DEMO_KEY)
rules_response1 = v.get_rules_json(product="DummyTest")
rules_response2 = v.get_rules_json(max_version="3.2.0", modules=['pe'])
rules_response3 = v.get_rules_json(max_version="3.2.0", modules=['pe'], with_crypto=False)
Expand All @@ -101,7 +100,7 @@ def test_demo_rules_tag_limited():
Retrieves the demo rules from the rule feed with custom expressions
:return:
"""
v = ValhallaAPI(api_key=DEMO_KEY)
v = ValhallaAPI(api_key=DEPRECATED_DEMO_KEY)
rules_response1 = v.get_rules_json()
rules_response2 = v.get_rules_json(tags=['APT'])
assert len(rules_response1['rules']) > 0
Expand All @@ -114,7 +113,7 @@ def test_demo_rules_score_limited():
Retrieves the demo rules from the rule feed with custom expressions
:return:
"""
v = ValhallaAPI(api_key=DEMO_KEY)
v = ValhallaAPI(api_key=DEPRECATED_DEMO_KEY)
rules_response1 = v.get_rules_json()
rules_response2 = v.get_rules_json(score=80)
assert len(rules_response1['rules']) > 0
Expand All @@ -127,7 +126,7 @@ def test_demo_rules_search_limited():
Retrieves the demo rules from the rule feed with custom expressions
:return:
"""
v = ValhallaAPI(api_key=DEMO_KEY)
v = ValhallaAPI(api_key=DEPRECATED_DEMO_KEY)
rules_response1 = v.get_rules_json()
rules_response2 = v.get_rules_json(search="Mimikatz")
assert len(rules_response1['rules']) > 1
Expand All @@ -140,7 +139,7 @@ def test_demo_rules_combo_limited():
Retrieves the demo rules from the rule feed with custom expressions
:return:
"""
v = ValhallaAPI(api_key=DEMO_KEY)
v = ValhallaAPI(api_key=DEPRECATED_DEMO_KEY)
rules_response1 = v.get_rules_json()
rules_response2 = v.get_rules_json(score=60)
rules_response3 = v.get_rules_json(tags=['SUSP'], score=60)
Expand All @@ -156,7 +155,7 @@ def test_demo_rules_text():
Retrieves the demo rules from the rule feed
:return:
"""
v = ValhallaAPI(api_key=DEMO_KEY)
v = ValhallaAPI(api_key=DEPRECATED_DEMO_KEY)
response = v.get_rules_text()
assert RULES_TEXT in response
assert len(response) > 500
Expand All @@ -172,33 +171,45 @@ def test_invalid_key():
v.get_rules_text()


def test_get_rule_info():
"""
Trying to retrieve info for a certain rule (the only one accessible with DEMO key)
:return:
"""
v = ValhallaAPI(api_key=DEMO_KEY)
response = v.get_rule_info('Casing_Anomaly_ByPass')
assert len(response) > 1
assert len(response['rule_matches']) > 0


def test_get_hash_info():
"""
Trying to retrieve info for a certain hash (the only one accessible with DEMO key)
:return:
"""
v = ValhallaAPI(api_key=DEMO_KEY)
response = v.get_hash_info('8a883a74702f83a273e6c292c672f1144fd1cce8ee126cd90c95131e870744af')
assert len(response) > 1
assert len(response['results']) > 0
# Remove test since demo key is deprecated
#def test_get_rule_info():
# """
# Trying to retrieve info for a certain rule (the only one accessible with DEMO key)
# :return:
# """
# v = ValhallaAPI(api_key=DEPRECATED_DEMO_KEY)
# response = v.get_rule_info('Casing_Anomaly_ByPass')
# assert len(response) > 1
# assert len(response['rule_matches']) > 0
#
#
#def test_get_hash_info():
# """
# Trying to retrieve info for a certain hash (the only one accessible with DEMO key)
# :return:
# """
# v = ValhallaAPI(api_key=DEPRECATED_DEMO_KEY)
# response = v.get_hash_info('8a883a74702f83a273e6c292c672f1144fd1cce8ee126cd90c95131e870744af')
# assert len(response) > 1
# assert len(response['results']) > 0


def test_demo_sigma_rules_json():
"""
Retrieves the demo rules from the sigma rule feed
:return:
"""
v = ValhallaAPI(api_key=DEMO_KEY)
v = ValhallaAPI(api_key=DEPRECATED_DEMO_KEY)
response = v.get_sigma_rules_json()
assert len(response['rules']) > 0

def test_get_rule_info_invalid():
"""
Retrieves no rules since key is invalid
:return:
"""
v = ValhallaAPI(api_key=INVALID_KEY)
response = v.get_rules_json()
assert response['status'] == 'error'
response2 = v.get_rules_json(score=75)
assert response2['status'] == 'error'
51 changes: 26 additions & 25 deletions valhallaAPI/valhalla.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class ValhallaAPI(object):

PRODUCT_IDENTIFIER = ['FireEyeAX', 'FireEyeNX', 'FireEyeEX', 'CarbonBlack', 'Tanium', 'Tenable', 'SymantecMAA',
'osquery', 'GRR', 'McAfeeATD3', 'McAfeeATD4']
DEMO_KEY = "1111111111111111111111111111111111111111111111111111111111111111"
# DEMO_KEY = "1111111111111111111111111111111111111111111111111111111111111111"
DEFAULT_OUTPUT_FILE = 'valhalla-rules.yar'

# Cached info
Expand All @@ -57,9 +57,9 @@ def __init__(self, api_key=""):
Initializes the API client object
:param api_key:
"""
# Demo API key if no API key was given
if api_key == "":
api_key = self.DEMO_KEY
# Demo API key if no API key was given -> empty API key if no API key was given
# if api_key == "":
# api_key = self.DEMO_KEY

# API Key
self.api_key = api_key
Expand Down Expand Up @@ -227,27 +227,28 @@ def get_rules_json(self, product="", max_version="", modules=[], with_crypto=Tru
rules_response = json.loads(r.text)

# Filter ------------------------------------------------------
# Product filtering
if product:
(max_version, modules, with_crypto) = get_product_requirements(product=product)
# Tag filtering
if len(tags) > 0:
rules_response['rules'] = filter_tags(rules_response['rules'], tags=tags)
# Score
if score > 0:
rules_response['rules'] = filter_score(rules_response['rules'], minimum_score=score)
# Search string
if search:
rules_response['rules'] = filter_search(rules_response['rules'], query=search)
# Custom filtering
if max_version or len(modules) > 0 or with_crypto is not True:
rules_response['rules'] = filter_requirements(rules_response['rules'],
sup_ver_string=max_version,
sup_modules=modules,
with_crypto=with_crypto)
# Public rules filter
if private_only:
rules_response['rules'] = filter_privateonly(rules_response['rules'])
if 'rules' in rules_response:
# Product filtering
if product:
(max_version, modules, with_crypto) = get_product_requirements(product=product)
# Tag filtering
if len(tags) > 0:
rules_response['rules'] = filter_tags(rules_response['rules'], tags=tags)
# Score
if score > 0:
rules_response['rules'] = filter_score(rules_response['rules'], minimum_score=score)
# Search string
if search:
rules_response['rules'] = filter_search(rules_response['rules'], query=search)
# Custom filtering
if max_version or len(modules) > 0 or with_crypto is not True:
rules_response['rules'] = filter_requirements(rules_response['rules'],
sup_ver_string=max_version,
sup_modules=modules,
with_crypto=with_crypto)
# Public rules filter
if private_only:
rules_response['rules'] = filter_privateonly(rules_response['rules'])

# Return filtered set
return rules_response
Expand Down