Categorygithub.com/ilyaglow/go-cortex
modulepackage
1.2.0
Repository: https://github.com/ilyaglow/go-cortex.git
Documentation: pkg.go.dev

# 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 protected]"},
		Status:  true,
	}, nil
}

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

# Functions

ExtractArtifacts extracts all artifacts from report string.
NewClient bootstraps a Client If there is a need to change the http.DefaultClient you should construct a Client struct by yourself.
NewInput grabs stdin and bootstraps cortex.JobInput.
SayError returns unsuccessful Report with an error message.
SayReport constructs Report by raw body and taxonomies.

# Constants

TxInfo is an info taxonomy level.
TxMalicious is a malicious taxonomy level.
TxSafe is a safe taxonomy level.
TxSuspicious is a suspicious taxonomy level.

# Variables

Rxs represents map of regexes.

# Structs

Analyzer defines a specific Cortex Analyzer More info: https://github.com/CERT-BDF/CortexDocs/blob/master/api/get-analyzer.md.
AnalyzerError is the report that analyzer app should return in case something went wrong.
AnalyzerReport is the report that analyzer app should return in case everything is okay.
Artifact represents a basic artifact which can be supplied for the analysis and retrieved from a job later.
ArtifactAttributes struct represents Artifact Attributes.
Client is used to deal with the API location and basic auth (in the future).
ExtractedArtifact is used for artifacts with slightly different structure.
FileArtifact represents a file observable.
FileArtifactMeta contains meta fields for FileArtifact.
Job defines an analysis job.
JobInput is used to track failed jobs and work with analyzer's input.
JobReport represents a job response.
JobsFilter is used to filter ListJobs results.
ReportBody defines a report for a given job.
Summary is a customized report object which may have taxonomies.
Taxonomy represents a taxonomy object in a report.

# Interfaces

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

# Type aliases

Cfg represents custom config field in the Analyzer definition.
JobBody is deprecated and is left for the compatilibity.