Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User Agent Analysis Integration #21

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 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
4 changes: 4 additions & 0 deletions fn_useragentanalysis/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
include README.md
include fn_useragentanalysis/util/*
include fn_useragentanalysis/LICENSE
include fn_useragentanalysis/doc/*
38 changes: 38 additions & 0 deletions fn_useragentanalysis/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
### User Agent Analysis
User agent analysis allows for the data enrichment on user agent strings found in web and firewall logs. These entries can provide clues as to potential attempted malicious access and what follow on steps are needed to restrict access.

Updates for config file
[fn_useragentanalysis]
url=WHAT_IS_MY_BROWSER_API_URL
api_key=WHAT_IS_MY_BROWSER_API_KEY
==

This template project was generated by

resilient-circuits codegen -p fn_useragentanalysis [-f fn_useragentanalysis] [-w user_agent_workflow]


You must edit the `setup.py` before distribution;
it should contain your actual contact and license information.

To install in "development mode"

pip install -e ./fn_useragentanalysis/

After installation, the package will be loaded by `resilient-circuits run`.


To uninstall,

pip uninstall fn_useragentanalysis


To package for distribution,

python ./fn_useragentanalysis/setup.py sdist

The resulting .tar.gz file can be installed using

pip install <filename>.tar.gz


Copy link
Collaborator

Choose a reason for hiding this comment

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

resilient-circuits config and then further editing to add url and api_key information

19 changes: 19 additions & 0 deletions fn_useragentanalysis/fn_useragentanalysis/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Copyright © IBM Corporation 2010, 2018

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
5 changes: 5 additions & 0 deletions fn_useragentanalysis/fn_useragentanalysis/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import pkg_resources
try:
__version__ = pkg_resources.get_distribution(__name__).version
except pkg_resources.DistributionNotFound:
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# -*- coding: utf-8 -*-
# pragma pylint: disable=unused-argument, no-self-use
"""Function implementation"""

import logging
import requests
from resilient_circuits import ResilientComponent, function, handler, StatusMessage, FunctionResult, FunctionError
import fn_useragentanalysis.util.selftest as selftest


class FunctionComponent(ResilientComponent):
"""Component that implements Resilient function 'fn_useragentanalysis"""

def __init__(self, opts):
"""constructor provides access to the configuration options"""
super(FunctionComponent, self).__init__(opts)
self.options = opts.get("fn_useragentanalysis", {})
selftest.selftest_function(opts)

@handler("reload")
def _reload(self, event, opts):
"""Configuration options have changed, save new values"""
self.options = opts.get("fn_useragentanalysis", {})

@function("fn_useragentanalysis")
def _fn_useragentanalysis_function(self, event, *args, **kwargs):
"""Function: As a SOC analysis, I want to perform data enrichment on user agent strings found in web and firewall logs. These entries can provide clues as to potential attempted malicious access and what follow on steps are needed to restrict access.

An integration function is required, sending an artifact string of user agent infromation to a user agent analysis website, returning detailed information as an incident note. An example workflow and rule to execute the function will be included in the packaging."""
try:
# Get the function parameters:
user_agent_string = kwargs.get("user_agent_string") # text

log = logging.getLogger(__name__)
log.info("user_agent_string: %s", user_agent_string)

url = self.options.get('url', None)
api_key = self.options.get('api_key', None)
if not url or not api_key:
raise ValueError('missing url and/or api_key from [fn_useragentanalysis] app_config')

# PUT YOUR FUNCTION IMPLEMENTATION CODE HERE
yield StatusMessage("starting...")
data = {"user_agent": user_agent_string}
headers = {'X-API-KEY': api_key}
api_response = requests.post(url, headers=headers, json=data)
if api_response.status_code != 200:
raise Exception("Unexpected return code of {}".format(api_response.status_code))

user_agent_analysis = api_response.text

results = {
"user_agent_string": user_agent_string,
"source_api_url": url,
"user_agent_analysis": user_agent_analysis
}
yield StatusMessage("done...")

# Produce a FunctionResult with the results
yield FunctionResult(results)
except Exception as e:
yield FunctionError(e)


1 change: 1 addition & 0 deletions fn_useragentanalysis/fn_useragentanalysis/util/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#
16 changes: 16 additions & 0 deletions fn_useragentanalysis/fn_useragentanalysis/util/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-

"""Generate a default configuration-file section for fn_useragentanalysis"""

from __future__ import print_function


def config_section_data():
"""Produce the default configuration section for app.config,
when called by `resilient-circuits config [-c|-u]`
"""
config_data = u"""[fn_useragentanalysis]
url=https://api.whatismybrowser.com/api/v2/user_agent_parse
api_key=<<customer key>>
"""
return config_data
Loading