If you wish to deploy in AWS, use this previous release.
Concrete Relay implementation using Farsight DNSDB as a third-party Cyber Threat Intelligence service provider.
The Relay itself is just a simple application written in Python that can be easily packaged and deployed. This relay is now Cisco Hosted and no longer requires AWS Lambda.
- We need an application that will translate API requests from SecureX Threat Response to the third-party integration, and vice versa.
- We need an application that can be completely self contained within a virtualized container using Docker.
Open the code folder in your terminal.
cd code
If you want to test the application you have to install a couple of extra dependencies from the Pipfile file:
pip install --no-cache-dir --upgrade pipenv && pipenv install --dev
You can perform two kinds of testing:
-
Run static code analysis checking for any semantic discrepancies and PEP 8 compliance:
flake8 .
-
Run the suite of unit tests and measure the code coverage:
coverage run --source api/ -m pytest --verbose tests/unit/ && coverage report
If you want to test the live Lambda you may use any HTTP client (e.g. Postman),
just make sure to send requests to your Lambda's URL
with the Authorization
header set to Bearer <JWT>
.
NOTE. If you need input data for testing purposes you can use data from the observables.json file.
In order to build the application, we need to use a Dockerfile
.
- Open a terminal. Build the container image using the
docker build
command.
docker build -t tr-05-farsight-dnsdb .
- Once the container is built, and an image is successfully created, start your container using the
docker run
command and specify the name of the image we have just created. By default, the container will listen for HTTP requests using port 9090.
docker run -dp 9090:9090 --name tr-05-farsight-dnsdb tr-05-farsight-dnsdb
- Watch the container logs to ensure it starts correctly.
docker logs tr-05-farsight-dnsdb
- Once the container has started correctly, open your web browser to http://localhost:9090. You should see a response from the container.
curl http://localhost:9090
This application was developed and tested under Python 3.9.
-
POST /health
- Verifies the Authorization Bearer JWT and decodes it to restore the original credentials.
- Authenticates to the underlying external service to check that the provided credentials are valid and the service is available at the moment.
-
POST /observe/observables
- Accepts a list of observables and filters out unsupported ones.
- Verifies the Authorization Bearer JWT and decodes it to restore the original credentials.
- Makes a series of requests to the underlying external service to query for some cyber threat intelligence data on each supported observable.
- Maps the fetched data into appropriate CTIM entities.
- Returns a list per each of the following CTIM entities (if any extracted):
Sighting
.
-
POST /refer/observables
- Accepts a list of observables and filters out unsupported ones.
- Builds a search link per each supported observable to pivot back to the underlying external service and look up the observable there.
- Builds a browse link per each supported observable to pivot back directly to the observable page if there is one.
- Returns a list of those links.
-
POST /version
- Returns the current version of the application.
ip
ipv6
domain
There are two possible mappings of Farsight historical Domain->IP resolution
to CTIM Sighting
which can be switched between with an environment variable AGGREGATE
.
-
If
Aggregated Mode
is off, eachresolution
generates a CTIMSighting
.- If an investigated observable is a
domain
, it is linked to eachIP
item from theresolution.rdata
field with an observed relationdomain->'Resolved_To'->IP
. - If an investigated observable is an
IP
, it is linked to adomain
from theresolution.rrname
field with an observed relationdomain->'Resolved_To'->IP
. - The resolution
count
field is used as aSighting.count
. - Each Farsight
resolution
is timestamped with at least one pair of fieldstime_first and time_last
(indicating the time an observable was seen via passive DNS replication) orzone_time_first and zone_time_list
(indicating the time an observable was seen via zone file import) which is used as aSighting.observed_time
. TheSighting.sensor
field depends on the time pair used and has a valuePassive DNS replication
orZone file import
correspondingly. If both pairs are presented,time_first and time_last
pair is used.
- If an investigated observable is a
-
If
Aggregated Mode
is on, allresolutions
for the last90 days
generate a single CTIMSighting
with unique values from the resolutionrdata
orrrname
fields linked asSighting
observed relations.- The sum of values from the resolution
count
is used as aSighting.count
. - The time of investigation is used as a
Sighting.observed_time.start_time
.
- The sum of values from the resolution
NOTE. If there are too many results, timeout or other performance issues may occur.