cortex

package module
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 23, 2018 License: AGPL-3.0 Imports: 13 Imported by: 0

README

GoDoc Build Status Codacy Badge Coverage Status

Usage example

go get -u github.com/ilyaglow/go-cortex

Analyze simple string type observable

package main

import (
	"log"

	"github.com/ilyaglow/go-cortex"
)

func main() {
	// Create a client struct
	client := cortex.NewClient("http://127.0.0.1:9000")

	// Fill the Artifact struct
	j := &cortex.Artifact{
		Data: "8.8.8.8",
		Attributes: cortex.ArtifactAttributes{
			DataType: "ip",
			TLP:      3,
		},
	}

	// Run all analyzers over it with 1 minute timeout
	reports, err := client.AnalyzeData(j, "1minute")
	if err != nil {
		panic(err)
	}
	
	// Iterate over channel with reports and get taxonomies
	for m := range reports {
		txs := m.Taxonomies()
		for _, t := range txs {
			log.Printf("\"%s:%s\"=\"%s\"", t.Namespace, t.Predicate, t.Value)
		}
	}
}

Analyze file type observable

Basically, any type that implements io.Reader could be analyzed.

package main

import (
	"log"
	"os"

	"github.com/ilyaglow/go-cortex"
)

func main() {

	client := cortex.NewClient("http://127.0.0.1:9000")

	// Open the file
	fname := "filename.exe"
	f, err := os.Open(fname)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	freports, err := client.AnalyzeData(&cortex.FileArtifact{
		FileArtifactMeta: cortex.FileArtifactMeta{
			DataType: "file",
			TLP:      3,
		},
		FileName: fname,
		Reader:   f,
	}, "5minutes")
	if err != nil {
		panic(err)
	}

	for m := range freports {
		if m.Status == "Failure" {
			log.Printf("%s failed with an error: %s\n", m.AnalyzerID, m.Report.ErrorMessage)
			continue
		}

		log.Println(m.Report.FullReport)
	}
}

Write your own analyzer

package main

import (
	"log"
	"strconv"

	"github.com/ilyaglow/go-cortex"
)

// Report is a sample analyzer report
type Report struct {
	Field   string   `json:"field,omitempty"`
	Results []string `json:"results,omitempty"`
	Status  bool     `json:"status,omitempty"`
}

func main() {
	// Grab stdin to JobInput structure
	input, err := cortex.NewInput()
	if err != nil {
		log.Fatal(err)
	}

	// Get url parameter from analyzer config
	url, err := input.Config.GetString("url")
	if err != nil {
		// Report an error if something went wrong
		cortex.SayError(input, err.Error())
	}

	// You get somehow report struct from JobInput.Data
	rep, err := Do(input.Data, url)
	if err != nil {
		cortex.SayError(input, err.Error())
	}

	// Make taxonomies
	var txs []cortex.Taxonomy
	namespace := "AnalyzerName"
	predicate := "Predicate"
	if len(rep.Results) == 0 {
		txs = append(txs, cortex.Taxonomy{
			Namespace: namespace,
			Predicate: predicate,
			Level:     "safe",
			Value:     "0",
		})
	} else {
		txs = append(txs, cortex.Taxonomy{
			Namespace: namespace,
			Predicate: predicate,
			Level:     "suspicious",
			Value:     strconv.FormatInt(int64(len(rep.Results[0])), 10),
		})
	}

	// Report accept marshallable struct and taxonomies
	cortex.SayReport(rep, txs)
}

// Do represents analyzing data
func Do(input string, u string) (*Report, error) {
	return &Report{
		Field:   "some",
		Results: []string{"domain.com", "127.0.0.1", "email@domain.com"},
		Status:  true,
	}, nil
}

You can see a real world examples at https://github.com/ilyaglow/go-cortex-analyzers.

Documentation

Overview

Package cortex is the client library for Cortex v1 API. Link: https://github.com/TheHive-Project/Cortex.

Check out Cortex v1 documentation: https://github.com/TheHive-Project/CortexDocs/tree/cortex-1

Example
package main

import (
	"log"

	cortex "github.com/ilyaglow/go-cortex"
)

func main() {
	// Create a client struct
	client := cortex.NewClient("http://127.0.0.1:9000")

	// Fill the Artifact struct
	j := &cortex.Artifact{
		Data: "8.8.8.8",
		Attributes: cortex.ArtifactAttributes{
			DataType: "ip",
			TLP:      3,
		},
	}

	// Run all analyzers over it with 1 minute timeout
	reports, err := client.AnalyzeData(j, "1minute")
	if err != nil {
		panic(err)
	}

	// Iterate over channel with reports and get taxonomies
	for m := range reports {
		txs := m.Taxonomies()
		for _, t := range txs {
			log.Printf("\"%s:%s\"=\"%s\"", t.Namespace, t.Predicate, t.Value)
		}
	}
}
Output:

Index

Examples

Constants

View Source
const (
	// TxSafe is a safe taxonomy level
	TxSafe = "safe"

	// TxInfo is an info taxonomy level
	TxInfo = "info"

	// TxSuspicious is a suspicious taxonomy level
	TxSuspicious = "suspicious"

	// TxMalicious is a malicious taxonomy level
	TxMalicious = "malicious"
)

Variables

View Source
var Rxs = map[string]*regexp.Regexp{
	"cc":              rxCC,
	"ipv4":            rxIPv4,
	"ipv6":            rxIPv6,
	"domain":          rxDomain,
	"email":           rxEmail,
	"hash":            rxHash,
	"registry":        rxRegistryKey,
	"url":             rxURL,
	"user-agent":      rxUserAgent,
	"bitcoin-address": rxBitcoinAddress,
}

Rxs represents map of regexes

Functions

func SayError added in v1.1.0

func SayError(input *JobInput, msg string)

SayError returns unsuccessful Report with an error message

func SayReport added in v1.1.0

func SayReport(body interface{}, taxs []Taxonomy)

SayReport constructs Report by raw body and taxonomies

Types

type Analyzer

type Analyzer struct {
	ID           string   `json:"id"`
	Name         string   `json:"name"`
	Description  string   `json:"description"`
	Version      string   `json:"version"`
	DataTypeList []string `json:"dataTypeList"`
}

Analyzer defines a specific Cortex Analyzer

More info: https://github.com/CERT-BDF/CortexDocs/blob/master/api/get-analyzer.md

type AnalyzerError added in v1.1.0

type AnalyzerError struct {
	Success      bool      `json:"success"`
	ErrorMessage string    `json:"errorMessage"`
	Input        *JobInput `json:"input"`
}

AnalyzerError is the report that analyzer app should return in case something went wrong

type AnalyzerReport added in v1.1.0

type AnalyzerReport struct {
	Artifacts  []ExtractedArtifact `json:"artifacts"`
	FullReport interface{}         `json:"full"`
	Success    bool                `json:"success"`
	Summary    *Summary            `json:"summary"`
}

AnalyzerReport is the report that analyzer app should return in case everything is okay

type Artifact

type Artifact struct {
	Attributes ArtifactAttributes `json:"attributes"`
	Data       string             `json:"data,omitempty"`
}

Artifact represents a basic artifact which can be supplied for the analysis and retrieved from a job later

func (*Artifact) Description

func (a *Artifact) Description() string

Description returns artifact data value

func (*Artifact) Type

func (a *Artifact) Type() string

Type returns datatype for an artifact

type ArtifactAttributes

type ArtifactAttributes struct {
	DataType    string `json:"dataType,omitempty"`
	TLP         int    `json:"tlp,omitempty"`
	ContentType string `json:"content-type,omitempty"`
	Filename    string `json:"filename,omitempty"`
}

ArtifactAttributes struct represents Artifact Attributes

type Cfg added in v1.1.0

type Cfg map[string]interface{}

Cfg represents custom config field in the Analyzer definition

func (Cfg) GetBool added in v1.1.0

func (c Cfg) GetBool(key string) (bool, error)

GetBool is a getter for bool type

func (Cfg) GetFloat added in v1.1.0

func (c Cfg) GetFloat(key string) (float64, error)

GetFloat is a getter for float64 type

func (Cfg) GetString added in v1.1.0

func (c Cfg) GetString(key string) (string, error)

GetString is a getter for string type

type Client

type Client struct {
	Location string       // Location is the Cortex base URL
	Client   *http.Client // Client is used to communicate with the API
	Debug    bool         // Debug mode
}

Client is used to deal with the API location and basic auth (in the future)

func NewClient

func NewClient(location string) *Client

NewClient bootstraps a Client If there is a need to change the http.DefaultClient you should construct a Client struct by yourself

func (*Client) AnalyzeData

func (c *Client) AnalyzeData(obs Observable, timeout string) (<-chan *JobReport, error)

AnalyzeData runs all analyzers suitable for a specified job and returns a channel with reports

func (*Client) DeleteJob

func (c *Client) DeleteJob(id string) (bool, error)

DeleteJob deletes an existing job identified by its ID

func (*Client) GetAnalyzer

func (c *Client) GetAnalyzer(id string) (*Analyzer, error)

GetAnalyzer retrieves an Analyzer by its' ID

func (*Client) GetJob

func (c *Client) GetJob(id string) (*Job, error)

GetJob retrieves a Job by its ID

func (*Client) GetJobReport

func (c *Client) GetJobReport(id string) (*JobReport, error)

GetJobReport retrieves a JobReport by Job ID

func (*Client) ListAnalyzers

func (c *Client) ListAnalyzers(datatype string) ([]Analyzer, error)

ListAnalyzers retrieves all analyzers that are available. Analyzers can be filtered by a datatype parameter. When "*" is used as a parameter, function returns all analyzers.

func (*Client) ListFilteredJobs

func (c *Client) ListFilteredJobs(f *JobsFilter) ([]Job, error)

ListFilteredJobs shows available filtered jobs

func (*Client) ListJobs

func (c *Client) ListJobs() ([]Job, error)

ListJobs shows all available jobs

func (*Client) RunAnalyzer

func (c *Client) RunAnalyzer(id string, obs Observable) (*Job, error)

RunAnalyzer runs a selected analyzer for a specified job

func (*Client) RunAnalyzerThenGetReport

func (c *Client) RunAnalyzerThenGetReport(id string, obs Observable, timeout string) (*JobReport, error)

RunAnalyzerThenGetReport is a helper function that combines multiple functions to return JobReport providing more clear API

func (*Client) WaitForJob

func (c *Client) WaitForJob(id string, duration string) (*Job, error)

WaitForJob do synchronously wait for a report Duration should be in a string format, for example:

1minute
30seconds

If the duration is too small a report with a null value will be returned

type ExtractedArtifact added in v1.1.0

type ExtractedArtifact struct {
	Type  string `json:"type"`
	Value string `json:"value"`
}

ExtractedArtifact is used for artifacts with slightly different structure

func ExtractArtifacts added in v1.1.0

func ExtractArtifacts(body string) []ExtractedArtifact

ExtractArtifacts extracts all artifacts from report string

type FileArtifact

type FileArtifact struct {
	FileArtifactMeta
	Reader   io.Reader // anything that implements io.Reader (os.File or http.Response.Body or whatever)
	FileName string    // could be filename or the URL
}

FileArtifact represents a file observable

func (*FileArtifact) Description

func (f *FileArtifact) Description() string

Description returns file name or URL

func (*FileArtifact) Type

func (f *FileArtifact) Type() string

Type implements observable function and should return "file"

type FileArtifactMeta

type FileArtifactMeta struct {
	DataType string `json:"dataType"`
	TLP      int    `json:"tlp"`
}

FileArtifactMeta contains meta fields for FileArtifact

type Job

type Job struct {
	ID         string   `json:"id"`
	AnalyzerID string   `json:"analyzerId"`
	Status     string   `json:"status"`
	Date       int64    `json:"date"`
	Artifact   Artifact `json:"artifact"`
}

Job defines an analysis job

type JobBody

type JobBody Artifact

JobBody is deprecated and is left for the compatilibity

type JobInput

type JobInput struct {
	ArtifactAttributes
	Data   string            `json:"data,omitempty"`
	File   string            `json:"file,omitempty"`
	Config Cfg               `json:"config,omitempty"`
	Proxy  map[string]string `json:"proxy,omitempty"`
}

JobInput is used to track failed jobs and work with analyzer's input

func NewInput added in v1.1.0

func NewInput() (*JobInput, error)

NewInput grabs stdin and bootstraps cortex.JobInput

type JobReport

type JobReport struct {
	Job
	Report ReportBody `json:"report"`
}

JobReport represents a job response.

More info: https://github.com/CERT-BDF/CortexDocs/blob/master/api/get-job-report.md

func (*JobReport) Taxonomies

func (j *JobReport) Taxonomies() []Taxonomy

Taxonomies retrieves all taxonomies from a JobReport

type JobsFilter

type JobsFilter struct {
	Analyzer string `url:"analyzerFilter,omitempty"`
	DataType string `url:"dataTypeFilter,omitempty"`
	Data     string `url:"dataFilter,omitempty"`
	// contains filtered or unexported fields
}

JobsFilter is used to filter ListJobs results

type Observable

type Observable interface {
	Type() string
	Description() string
}

Observable is an interface for string type artifact and file type artifact

type ReportBody

type ReportBody struct {
	Artifacts    []Artifact  `json:"artifacts,omitempty"`
	FullReport   interface{} `json:"full,omitempty"`
	Success      bool        `json:"success,omitempty"`
	Summary      *Summary    `json:"summary,omitempty"`
	ErrorMessage string      `json:"errorMessage,omitempty"`
	Input        *JobInput   `json:"input,omitempty"`
}

ReportBody defines a report for a given job. FullReport and Summary are arbitrary objects.

type Summary added in v1.1.0

type Summary struct {
	Taxonomies []Taxonomy `json:"taxonomies,omitempty"`
}

Summary is a customized report object which may have taxonomies

type Taxonomy

type Taxonomy struct {
	Predicate string `json:"predicate"`
	Namespace string `json:"namespace"`
	Value     string `json:"value"`
	Level     string `json:"level"`
}

Taxonomy represents a taxonomy object in a report

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL