Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/targetid #152

Merged
merged 4 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ Desktop.ini

.vscode/


# Temp

playground/_output
Expand All @@ -50,4 +49,5 @@ release/
docs/.vitepress/dist/
docs/.vitepress/cache/

local/
local/
dist/
26 changes: 25 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,32 @@

All notable changes to this project will be documented in this file.

<br><br>

## Unreleased - feature/loadremote
## EXPERIMENTAL FEATURE - feature/targetid

**Commit**: [b84f0f9](https://github.com/xfhg/intercept/commit/b84f0f9)

**Branch** [feature/targetid](https://github.com/xfhg/intercept/tree/feature/targetid)

**Summary**: Fingerprint hosts for reporting --experimental

### Breaking
- Properties on Final SARIF report key names corrected to kebab case.

### Added
- Added Global hostData & hostFingerprint
- Added "host-data" & "host-fingerprint" to Final SARIF Report

### Changed
- Properties on Final SARIF report key names corrected to kebab case.

### Removed
- None

<br><br><br><br>

## FEATURE - feature/loadremote

**Commit**: [e95c0ed](https://github.com/xfhg/intercept/commit/e95c0ed)

Expand Down
13 changes: 10 additions & 3 deletions cmd/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ type Config struct {
ReportSchedule string `yaml:"report_schedule"`
} `yaml:"Flags"`
Metadata struct {
HostOS string `yaml:"host_os,omitempty"`
HostMAC string `yaml:"host_mac,omitempty"`
HostARCH string `yaml:"host_arch,omitempty"`
HostNAME string `yaml:"host_name,omitempty"`
HostFingerprint string `yaml:"host_fingerprint,omitempty"`
HostInfo string `yaml:"host_info,omitempty"`
MsgExitClean string `yaml:"MsgExitClean"`
MsgExitWarning string `yaml:"MsgExitWarning"`
MsgExitCritical string `yaml:"MsgExitCritical"`
Expand Down Expand Up @@ -146,14 +152,15 @@ func LoadPolicyFile(filename string) (*PolicyFile, error) {
// LoadRemotePolicy loads a policy file from a remote HTTPS endpoint
func LoadRemotePolicy(url string, expectedChecksum string) (*PolicyFile, error) {
// Create a temporary directory to store the downloaded file
tempDir, err := os.MkdirTemp(outputDir, "_remote")
remoteDir := filepath.Join(outputDir, "_remote")
err := os.MkdirAll(remoteDir, 0755)
if err != nil {
return nil, fmt.Errorf("failed to create temporary directory: %w", err)
}
defer os.RemoveAll(tempDir) // Clean up the temporary directory when done
defer os.RemoveAll(remoteDir) // Clean up the temporary directory when done

// Generate a temporary file name
tempFile := filepath.Join(tempDir, "remote_policy.yaml")
tempFile := filepath.Join(remoteDir, "remote_policy.yaml")

// Create a resty client
client := resty.New()
Expand Down
25 changes: 25 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ var (
silentMode bool
nologMode bool

hostData string
hostFingerprint string

buildVersion string
buildSignature string

Expand Down Expand Up @@ -94,8 +97,30 @@ func setupLogging() {
log = zerolog.New(output).With().Timestamp().Logger()

if experimentalMode {

// ----------------------------------------------
// ---------------------------------------------- EXPERIMENTAL log caller debug
// ----------------------------------------------

log = zerolog.New(output).With().Timestamp().Logger().With().Caller().Logger()
// log = zerolog.New(output).With().Timestamp().Logger().With().Str("id", intercept_run_id).Logger()

// ----------------------------------------------
// ---------------------------------------------- EXPERIMENTAL feature/targetid
// ----------------------------------------------

hostInfo, err := GetHostInfo()
if err != nil {
log.Error().Msgf("Error gathering host info: %v\n", err)
}

hostData, hostFingerprint, err := FingerprintHost(hostInfo)
if err != nil {
log.Error().Msgf("Error generating fingerprint: %v\n", err)
}
log.Info().Msgf("Host Data: %s", hostData)
log.Info().Msgf("Host Fingerprint: %s", hostFingerprint)

}
if silentMode {

Expand Down
31 changes: 22 additions & 9 deletions cmd/sarif.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"path/filepath"
"strings"
"time"

"github.com/charlievieth/fastwalk"
)

// SARIFLevel represents the severity level in SARIF format
Expand Down Expand Up @@ -127,9 +129,14 @@ type ArtifactLocation struct {
}

type Region struct {
StartLine int `json:"startLine"`
StartColumn int `json:"startColumn"`
EndColumn int `json:"endColumn"`
StartLine int `json:"startLine"`
StartColumn int `json:"startColumn"`
EndColumn int `json:"endColumn"`
Snippet Snippet `json:"snippet"`
}

type Snippet struct {
Text string `json:"text"`
}

type Invocation struct {
Expand Down Expand Up @@ -204,7 +211,8 @@ func GenerateSARIFReport(inputFile string, policy Policy) (SARIFReport, error) {
},
},
Properties: map[string]string{
"result-type": "detail", "observe-run-id": policy.RunID,
"result-type": "detail",
"observe-run-id": policy.RunID,
"result-timestamp": timestamp,
"name": policy.Metadata.Name,
"description": policy.Metadata.Description,
Expand Down Expand Up @@ -234,6 +242,9 @@ func GenerateSARIFReport(inputFile string, policy Policy) (SARIFReport, error) {
StartLine: rgOutput.Data.LineNumber,
StartColumn: strings.Index(rgOutput.Data.Lines.Text, matchText) + 1,
EndColumn: strings.Index(rgOutput.Data.Lines.Text, matchText) + len(matchText) + 1,
Snippet: Snippet{
Text: matchText,
},
},
},
},
Expand Down Expand Up @@ -545,13 +556,15 @@ func MergeSARIFReports(commandLine string, perf Performance, isScheduled bool) (
ExecutionSuccessful: true,
CommandLine: commandLine,
Properties: map[string]string{
"run_id": intercept_run_id,
"start_time": perf.StartTime.Format(time.RFC3339),
"end_time": perf.EndTime.Format(time.RFC3339),
"execution_time_ms": fmt.Sprintf("%d", perf.Delta.Milliseconds()),
"run-id": intercept_run_id,
"start-time": perf.StartTime.Format(time.RFC3339),
"end-time": perf.EndTime.Format(time.RFC3339),
"execution-time-ms": fmt.Sprintf("%d", perf.Delta.Milliseconds()),
"environment": environment,
"debug": fmt.Sprintf("%v", debugOutput),
"report-timestamp": timestamp,
"host-data": hostData,
"host-fingerprint": hostFingerprint,
},
},
},
Expand Down Expand Up @@ -634,7 +647,7 @@ func cleanupSARIFFolder() error {
sarifDir = filepath.Join(outputDir, sarifDir)
}

err := filepath.WalkDir(sarifDir, func(path string, d fs.DirEntry, err error) error {
err := fastwalk.Walk(nil, sarifDir, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err // Error accessing the path
}
Expand Down
7 changes: 5 additions & 2 deletions cmd/target.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ package cmd
import (
"encoding/json"
"fmt"
"io/fs"
"os"
"path/filepath"
"regexp"
"strings"

"github.com/charlievieth/fastwalk"
)

type FileInfo struct {
Expand All @@ -21,12 +24,12 @@ func CalculateFileHashes(targetDir string) ([]FileInfo, error) {

ignorePaths := policyData.Config.Flags.Ignore

err := filepath.Walk(targetDir, func(path string, info os.FileInfo, err error) error {
err := fastwalk.Walk(nil, targetDir, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}

if !info.IsDir() && !isIgnored(ignorePaths, path) {
if !d.IsDir() && !isIgnored(ignorePaths, path) {

hash, err := calculateSHA256(path)
if err != nil {
Expand Down
83 changes: 83 additions & 0 deletions cmd/watch.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
package cmd

import (
"crypto/sha256"
"encoding/hex"
"fmt"
"net"
"os"
"runtime"
"strings"
"time"

"github.com/fsnotify/fsnotify"
"github.com/segmentio/ksuid"
)

type HostInfo struct {
Hostname string
OS string
Architecture string
IPs []string
MAC string
}

func watchPaths(paths ...string) {
if len(paths) < 1 {
log.Fatal().Msg("must specify at least one path to watch")
Expand Down Expand Up @@ -95,3 +109,72 @@ func processEvent(e fsnotify.Event) {
log.Error().Msgf("Policy not found in cache, watcher event [%s] didn't trigger policy process for: %s", e.Op.String(), e.Name)
}
}

func GetHostInfo() (*HostInfo, error) {
hostInfo := &HostInfo{}

// Get hostname
hostname, err := os.Hostname()
if err != nil {
return nil, fmt.Errorf("failed to get hostname: %v", err)
}
hostInfo.Hostname = hostname

// Get OS and architecture
hostInfo.OS = runtime.GOOS
hostInfo.Architecture = runtime.GOARCH

// Get IPs and MAC addresses
interfaces, err := net.Interfaces()
if err != nil {
return nil, fmt.Errorf("failed to get network interfaces: %v", err)
}

for _, iface := range interfaces {
if iface.Flags&net.FlagUp == 0 {
continue // ignore interfaces that are down
}

addrs, err := iface.Addrs()
if err != nil {
return nil, fmt.Errorf("failed to get addresses for interface %v: %v", iface.Name, err)
}

for _, addr := range addrs {
ip, _, err := net.ParseCIDR(addr.String())
if err != nil {
return nil, fmt.Errorf("failed to parse IP address %v: %v", addr.String(), err)
}

if ip.IsLoopback() {
continue // ignore loopback addresses
}

hostInfo.IPs = append(hostInfo.IPs, ip.String())
}
// main MAC
if iface.Flags&net.FlagUp != 0 && iface.HardwareAddr.String() != "" {
hostInfo.MAC = iface.HardwareAddr.String()
}

}

return hostInfo, nil
}

// FingerprintHost generates a fingerprint for the host using its identifiable information
func FingerprintHost(hostInfo *HostInfo) (string, string, error) {
data := strings.Join([]string{
hostInfo.MAC,
hostInfo.OS,
hostInfo.Architecture,
hostInfo.Hostname,
}, "|")
hash := sha256.New()
_, err := hash.Write([]byte(data))
if err != nil {
return "", "", fmt.Errorf("failed to generate hash: %v", err)
}
fingerprint := hex.EncodeToString(hash.Sum(nil))
return data, fingerprint, nil
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ require (
require (
cuelang.org/go v0.10.0
github.com/adhocore/gronx v1.19.0
github.com/charlievieth/fastwalk v1.0.8
github.com/cockroachdb/apd/v3 v3.2.1 // indirect
github.com/fsnotify/fsnotify v1.7.0
github.com/go-resty/resty/v2 v2.14.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/charlievieth/fastwalk v1.0.8 h1:uaoH6cAKSk73aK7aKXqs0+bL+J3Txzd3NGH8tRXgHko=
github.com/charlievieth/fastwalk v1.0.8/go.mod h1:yGy1zbxog41ZVMcKA/i8ojXLFsuayX5VvwhQVoj9PBI=
github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg=
github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
Expand Down