Integrate the DocuSign Monitor API into your SIEM

DocuSign Monitor protects your agreements with round-the-clock activity tracking. It provides near-real-time knowledge about your day-to-day transactions on your DocuSign agreements and processes. Using advanced analytics to track DocuSign web, mobile, and API account activity across your organization, Monitor helps security teams:

  • Detect potential threats
  • Investigate incidents
  • Respond decisively

Integrating with the DocuSign Monitor API is very easy. This blog describes how to get data from DocuSign Monitor into your Security and Intelligence Management (SIEM) or Business Intelligence (BI) software of choice.

Retrieving DocuSign Monitoring data from the API is a straightforward three-step process repeated on an interval. We recommend using an interval of 1–5 minutes, depending on how much data your organization generates.

The retrieval steps include:

  1. Authenticate: Retrieve an access token for calling the DocuSign Monitor API.
  2. Request DocuSign Monitor events: A single API endpoint takes a cursor parameter and a limit for the number of desired events.
  3. Persist the cursor: Your subsequent API request uses the cursor returned from the prior call to know where you left off.

Authenticate

Before making the DocuSign Monitor API request, you must authenticate with DocuSign and retrieve an API access token. DocuSign Monitor supports the Json Web Token (JWT) Grant scenario. Follow the directions to set up your app and integration key and obtain your individual consent. For DocuSign Monitor, you must request impersonation consent.

We recommend setting up a service user for your DocuSign Monitor integration. This service user must have DocuSign Administrator privileges. The Security Reports Administrator role is restricted only to reporting, including DocuSign Monitor and is a good one to choose.

Once you have the user and consent configured, you can start making authentication requests! This example shows using Python to construct the JWT and then use it to make a request to our authentication servers to get an access token.

import time
import math
import requests
import jwt
 
# All the fields required from your DocuSign Account to make the request:
# UserId, Integrator Key, RSA Private Key and the authorization and monitor URLs
import config
 
# Construct the JWT using the integrator key and user id for the claims
now = math.floor(time.time())
later = now + 3600
claim = {
    "iss": config.INTEGRATOR_KEY,
    "aud": config.AUTH_HOST, 
    "iat": now, 
    "exp": later, 
    "scope": "impersonation", 
    "sub": config.USER_ID
}
token = jwt.encode(payload=claim, key=config.RSA_KEY, algorithm='RS256')
 
# Make the authorization request using the above JWT as the assertion
auth_headers = {"Content-Type": "application/json;charset=UTF-8"}
response_data = requests.post(config.AUTH_SERVER, headers=auth_headers, json={
    "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
    "assertion": token
})
 
# Get the access token out of the auth request
response = response_data.json()
access_token = response['access_token']

Once you have your access token, you are ready to begin requesting DocuSign Monitor data.

Request DocuSign Monitor events

The DocuSign Monitor API includes a DataSet: getStream endpoint. You need to make a GET request to the proper URL and pass along these query parameters:

  • cursor: The previous checkpoint returned from an earlier call to the endpoint, and discussed in Cursors and Remembering where you left off. Omitting this parameter defaults to beginning from the earliest available data for your organization.
  • limit: The number of records you want in one call (maximum 2000). The actual returned number may be fewer if there are fewer available events or if you have caught up to current time.

This Python example shows a request using the access token received during the authentication step above:

# Include the access token from the auth request in the bearer token
monitor_headers = {"Authorization": f"Bearer {access_token}"}
monitor_response = requests.get(
    config.MONITOR_URL,
    params={'cursor': existingCheckPoint, 'limit': config.FETCH_LIMIT},
    headers=monitor_headers
)
 
monitor_data = monitor_response.json()

Use the data

After receiving a big data set from DocuSign Monitor, you can now integrate that information into your SIEM or other reporting software.

The following Splunk example uses the Splunk SDK to make a Modular Input:

import dateutil.parser as dp
 
# Write out all the events to the event writer, override the timestamp
# with the event's timestamp
for ev in monitor_data["data"]:
    parsed_t = dp.parse(ev['timestamp'])
 
    event = Event() # A splunk event type
    event.time = parsed_t.timestamp()
    event.sourcetype: 'ds_monitor'
    event.data = json.dumps(ev)
 
    splunk_event_writer.write_event(event)

Similarly, you could POST the data set to Splunk using the HTTP Event Collector

Use this code as a template for your SEIM or reporting software that has its own integration method that is similar in concept.

Use cursors to remember where you left off

When you requested the DocuSign Monitor events, you sent a cursor (or omitted it) along with the DocuSign Monitor request. This cursor indicates where you left off on retrieving data. Therefore, on the subsequent call, Monitor picks up at that point and provides the next batch of data. If you omitted a cursor, Monitor starts at the earliest available data; and if you supplied a cursor, Monitor starts at that checkpoint. With either method, the response includes the new cursor for you.

# Get the new cursor for the next call out of the response and persist it
newCursor = monitor_data['endCursor']

Save this information somewhere for your integration’s subsequent run. Save this simple string as text so that it’s readily available.

file = open("cursor.txt", "w") 
file.write(str(newCursor))
file.close()

On the next run, retrieve your saved cursor as shown in this example:

# Get existing cursor from the prior iteration
file = open("cursor.txt", "r")  
existingCheckPoint = file.read()
file.close()

Supply this with the cursor parameter on your next call, and you are good to go!

Extend the data

You may notice that the data returned from DocuSign Monitor includes unique identifiers for your users and account information, and not the actual names or email addresses.

We recommend that you make API calls into our eSignature and Organization Admin APIs to retrieve this additional information.

  • Users: Get your users’ information from our Users: list endpoint. You need to grant signature scope consent to your DocuSign Monitor API user for this feature.
  • Accounts: Get your account’s information from our Accounts: getOrganizations endpoint. You need to grant organization_read consent to your DocuSign Monitor API user for this feature.

Once you have this data, you can also push it to your SIEM or reporting software in similar fashion as previously described. For example, in Splunk push the data into lookup tables that allow joining of the two datasets containing all the event information as well as the user and account information.

Example data

The following example shows the dataset that is returned from the streaming endpoint that includes the new cursor (endCursor) and an array of events. For a more detailed explanation of the schema, see DocuSign Monitor Events and Alerts.

{
    "endCursor": "aa_637218935854425652_637218935412032088_12",
    "data": [
        {
            "timestamp": "2020-04-07T18:23:02.5539916Z",
            "eventId": "cb33xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
            "site": "DEMO",
            "accountId": "2ed737ad-xxxx-xxxx-xxxx-xxxxxxxxxxx",
            "organizationId": "",
            "userId": "01cbxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
            "integratorKey": "f48fxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
            "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36",
            "userAgentClientInfo": {
                "browser": {
                    "family": "Chrome",
                    "version": {
                        "major": "80",
                        "minor": "0",
                        "patch": "3987"
                    }
                },
                "device": {
                    "family": "Other",
                    "brand": "",
                    "model": ""
                },
                "os": {
                    "family": "Windows",
                    "version": {
                        "major": "10"
                    }
                }
            },
            "ipAddress": "208.xxx.xxx.xxx",
            "ipAddressLocation": {
                "latitude": 47.61,
                "longitude": -122.33,
                "country": "US",
                "state": "Washington",
                "city": "King"
            },
            "object": "Account",
            "action": "UserAdded",
            "property": "",
            "field": "",
            "result": "",
            "data": {
                "AffectedUserId": "8b34xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
                "AffectedMembershipId": "cb81xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx"
            }
        },
        {
            "timestamp": "2020-04-07T18:23:06.9734612Z",
            "eventId": "0582xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
            "site": "DEMO",
            "accountId": "2ed7xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
            "organizationId": "",
            "userId": "01cbxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
            "integratorKey": "f48fxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
            "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36",
            "userAgentClientInfo": {
                "browser": {
                    "family": "Chrome",
                    "version": {
                        "major": "80",
                        "minor": "0",
                        "patch": "3987"
                    }
                },
                "device": {
                    "family": "Other",
                    "brand": "",
                    "model": ""
                },
                "os": {
                    "family": "Windows",
                    "version": {
                        "major": "10"
                    }
                }
            },
            "ipAddress": "208.xxx.xxx.xxx",
            "ipAddressLocation": {
                "latitude": 47.61,
                "longitude": -122.33,
                "country": "US",
                "state": "Washington",
                "city": "King"
            },
            "object": "Account",
            "action": "AddAdministrator",
            "property": "",
            "field": "",
            "result": "",
            "data": {
                "AffectedUserId": "8b3xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
                "AffectedMembershipId": "cb8xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx"
            }
        }
    ]
}

 

Additional resources

Brian Yeckley
Author
Brian Yeckley
Sr. Software Engineer
Published