How to Use Gravwell's REST API for Automation

Modified on Wed, 21 Aug, 2024 at 7:37 PM

Gravwell provides a REST API that provides access to the Gravwell query system. This API can be used to automate integrations with external tools. This document will provide an example script for using Gravwell's REST API for automation.


Resources:


Generate an API Token


The Tokens API interface is located in the “Tools & Resources” navigation section.


The default interface of the Tokens API page shows all the currently constructed tokens, both expired and not. 

Select Add Token


Permissions can be selected in groups or as fine controls. For example, you can select the “Search and Data” group which will automatically fill in all the API permissions required to interact with the search system. This includes executing searches, getting the search history, downloading, saving, and attaching to searches.


After populating your new token with a name, description, permissions, and an optional expiration it is time to actually make the token by clicking the Save button. At this point Gravwell will create the token and provide it to you. Copy this token for use in your code. !NOTE: This token will never be provided again and can only be regenerated.



Querying Data

To test the API Token you can use curl to run a search, this will run the query 'tag=gravwell limit 10' over the last 24h and output as csv:


curl -X POST \
-H "Gravwell-Token: HmrAgIKlKP6hCGBJvFIABUFFyrdyTwrIlmlHH4a4cynwSBF5EFA" \
-H "query: tag=gravwell limit 10" \
-H "duration: 24h" \
-H "format: csv" \
http://127.0.0.1:8080/api/search/direct


Example Output:


Example Scripts


The following is a few scripts each shows a similar simple example where we query the API and write the results to an output file.


Example Bash Script:

#!/usr/bin/env bash

### GLOBALS
# Define the API token for authentication with the Gravwell server
GRAVWELL_API_TOKEN="HmrAgIKlKP6hCGBJvFIABUFFyrdyTwrIlmlHH4a4cynwSBF5EFA"

# Define the Gravwell server URL and port
GRAVWELL_SERVER="127.0.0.1:8080"

# Generate a timestamp for the filename to ensure each report is uniquely named
DATE=$(date +%Y_%b_%d_%H:%M)

# Function to query data from Gravwell and save it as a CSV file
get_gravwell(){
    # Define the query to use for the API request
    gravwell_query="tag=gravwell limit 10"
    # Define the URL of the Gravwell Web Server to send the API request
    url="http://$GRAVWELL_SERVER/api/search/direct"

    # Use curl to query the API
    # - The request is silent and does not show progress or error messages
    # - The HTTP response code is captured and stored in 'resp'
    # - The output is saved to a CSV file named with the current date and time
    resp=$(curl --silent --write-out "%{http_code}" \
            --output "./${DATE}_GravwelReport.csv" \
            -X POST \
            -H "Gravwell-Token: $GRAVWELL_API_TOKEN" \
            -H "query: $gravwell_query" \
            -H "duration: 24h" \
            -H "format: csv" \
            $url
        )

    # Check the HTTP response code
    if [ $resp == "200" ]; then
        # Print success message if HTTP code is 200
        echo "[INFO] API call successful"
    else
        # Print error message if request was not successful
        echo "[ERROR] API call unsuccessful server responded with HTTP code: $resp"
    fi

}

# Call the function to execute the API request
get_gravwell


Example Python Script

#!/usr/bin/env python3

import requests
from datetime import datetime

### GLOBALS
# Define the API token for authentication with the Gravwell server
GRAVWELL_API_TOKEN="HmrAgIKlKP6hCGBJvFIABUFFyrdyTwrIlmlHH4a4cynwSBF5EFA"

# Define the Gravwell server URL and port
GRAVWELL_SERVER="127.0.0.1:8080" 

# Generate a timestamp for the filename to ensure each report is uniquely named
DATE=datetime.now().strftime('%Y_%b_%d_%H:%M') 

# Function to query data from Gravwell and save it as a text file
def get_gravwell():
    # Define the query to use for the API request
    gravwell_query="tag=gravwell limit 10"
    # Define the URL of the Gravwell Web Server to send the API request
    url = f"http://{GRAVWELL_SERVER}/api/search/direct"
    headers = {
        'Gravwell-Token': f'{GRAVWELL_API_TOKEN}',
        'query': f'{gravwell_query}',
        'duration': '24h',
        'format': 'text'
    }
    
    # Use response to query the API
    response = requests.post(url, headers=headers)

    # Check the HTTP response code to determine if the request was successful
    if response.status_code == 200:
        # Write HTML response to file
        with open(f"{DATE}_GravwellReport.txt", "w") as f:
            f.write(response.text)

        # Print success message if HTTP code is 200
        print("[INFO] API call successful")
    else:
        # Print error message if request was not successful
        print(f"[ERROR] API call unsuccessful server responded with HTTP code: {response.status_code}")

def main():
    # Call the function to execute the API request
    get_gravwell()

if __name__ == "__main__":
    main()


Example Go Script

package main

import (
	"crypto/tls"
	"fmt"
	"io"
	"net/http"
	"os"
	"time"
)

// GLOBALS
// Define the API token for authentication with the Gravwell server
var GRAVWELL_API_TOKEN = "HmrAgIKlKP6hCGBJvFIABUFFyrdyTwrIlmlHH4a4cynwSBF5EFA"

// Define the Gravwell server URL and port
var GRAVWELL_SERVER = "127.0.0.1:8080"

// Generate a timestamp for the filename to ensure each report is uniquely named
var DATE = time.Now().Format("2006_01_02_15_04")

// Function to query data from Gravwell and save it as a json file
func get_gravwell() {
	// Define the query to use for the API request
	gravwell_query := "tag=gravwell limit 10"
	// Define the URL of the Gravwell Web Server to send the API request
	url := "http://" + GRAVWELL_SERVER + "/api/search/direct"

	request, err := http.NewRequest(http.MethodPost, url, nil)
	if err != nil {
		fmt.Printf("[ERROR] client: could not create request: %s\n", err)
		os.Exit(1)
	}
	request.Header.Add("Gravwell-Token", GRAVWELL_API_TOKEN)
	request.Header.Add("query", gravwell_query)
	request.Header.Add("duration", "24h")
	request.Header.Add("format", "json")

	tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
	client := http.Client{Transport: tr}

	// Use response to query the API
	response, err := client.Do((request))
	if err != nil {
		fmt.Printf("[ERROR] sending Request: %v\n", err)
		return
	}
	defer response.Body.Close()

	// Check the HTTP response code to determine if the request was successful
	if response.StatusCode == 200 {
		// Write HTML response to file
		f, err := os.Create(DATE + "_GravwellReport.json")
		if err != nil {
			fmt.Printf("[ERROR] Error creating output file\n")
			return
		}
		defer f.Close()
		io.Copy(f, response.Body)

		// Print success message if HTTP code is 200
		fmt.Printf("[INFO] API call successful\n")
	} else {
		// Print error message if request was not successful
		fmt.Printf("[ERROR] API call unsuccessful server responded with HTTP code:" + string(response.StatusCode) + "\n")
	}
}

func main() {
	get_gravwell()
}


Conclusion

Gravwell’s REST API allows you to automate your data queries, manage saved queries, and integrate Gravwell with other tools and systems. By following this guide, you should be able to get started with basic API interactions and incorporate them into your automation workflows.


For more detailed information, refer to the Gravwell API documentation or reach out to us through your customer support representative or our Discord.

Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article