Files
go-snow/main.go
Nathan Coad b50075083e
All checks were successful
continuous-integration/drone Build is passing
first commit
2025-03-12 19:43:25 +11:00

198 lines
5.4 KiB
Go

package main
import (
"bytes"
"encoding/base64"
"encoding/json"
"flag"
"fmt"
"io"
"log"
"net/http"
"net/url"
"os"
"runtime"
"time"
)
type Incident struct {
AppID string `json:"app_id"`
Resource string `json:"resource"`
Node string `json:"node"`
ShortDescription string `json:"short_description"`
MetricName string `json:"metric_name"`
MessageKey string `json:"message_key"`
MetricValue string `json:"metric_value"`
Source string `json:"source"`
Description string `json:"description"`
EventClass string `json:"event_class"`
Severity int `json:"severity"`
Type string `json:"type"`
AssignmentGroup string `json:"assignment_group"`
Environment string `json:"environment"`
}
// ValidAuthMethods defines the allowed authentication methods.
//var ValidAuthMethods = []string{"no-auth", "basic", "ntlm"}
var (
sha1ver string // sha1 revision used to build the program
buildTime string // when the executable was built
)
/*
// ValidateAuthMethod checks if the provided auth method is valid.
func ValidateAuthMethod(authMethod string) error {
for _, validMethod := range ValidAuthMethods {
if authMethod == validMethod {
return nil
}
}
return errors.New("invalid authentication method: " + authMethod)
}
*/
func prettyPrint(args ...interface{}) {
var caller string
timeNow := time.Now().Format("01-02-2006 15:04:05")
prefix := fmt.Sprintf("[%s] %s -- ", "PrettyPrint", timeNow)
_, fileName, fileLine, ok := runtime.Caller(1)
if ok {
caller = fmt.Sprintf("%s:%d", fileName, fileLine)
} else {
caller = ""
}
log.Printf("\n%s%s\n", prefix, caller)
if len(args) == 2 {
label := args[0]
value := args[1]
s, _ := json.MarshalIndent(value, "", "\t")
fmt.Printf("%s%s: %s\n", prefix, label, string(s))
} else {
s, _ := json.MarshalIndent(args, "", "\t")
log.Printf("%s%s\n", prefix, string(s))
}
}
func main() {
// Command line flags for the vCenter connection
snowURL := flag.String("url", "https://server.domain.example/api/global/em/inbound_event", "The URL of the SNOW endpoint")
snowUser := flag.String("user", "username", "The username to use when authenticating to SNOW")
snowPass := flag.String("password", "password", "The password to use when authenticating to SNOW")
proxyURL := flag.String("p-url", "", "The URL of the SNOW endpoint, including protocol and port. Eg http://proxy.domain.example:8080")
// proxyUser := flag.String("p-user", "", "The username to use when authenticating to the proxy")
// proxyPass := flag.String("p-pass", "", "The password to use when authenticating to the proxy")
// proxyDomain := flag.String("p-domain", "", "The domain to use when authenticating to the proxy with NTLM authentication")
payload := flag.String("payload", "{}", "The JSON formatted payload to send to SNOW")
flag.Parse()
// Print logs to file
f, err := os.OpenFile("log.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Fatalf("error opening file: %v", err)
}
defer f.Close()
log.SetOutput(f)
//log.Printf("Starting execution. Built on %s from sha1 %s\n", buildTime, sha1ver)
/*
if err := ValidateAuthMethod(*proxyType); err != nil {
log.Fatalf("error validating auth method '%s': %s\n", *proxyType, err)
} else {
fmt.Println("Valid auth method:", *proxyType)
}
*/
// Validate the incoming payload
var incident Incident
if err := json.Unmarshal([]byte(*payload), &incident); err != nil {
fmt.Printf("Error unmarshaling JSON: %s\n", err)
os.Exit(1)
} else {
prettyPrint(incident)
}
// Configure proxy transport
var transport http.RoundTripper = http.DefaultTransport
if *proxyURL != "" {
proxy, err := url.Parse(*proxyURL)
if err != nil {
fmt.Println("Invalid proxy URL:", err)
return
}
// Base transport with proxy
// baseTransport := &http.Transport{Proxy: http.ProxyURL(proxy)}
transport = &http.Transport{Proxy: http.ProxyURL(proxy)}
/*
// If NTLM credentials are provided, wrap the transport
if *proxyUser != "" && *proxyPass != "" {
// create a dialer
dialer := &net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}
// wrap dial context with NTLM
ntlmDialContext := ntlm.NewNTLMProxyDialContext(dialer, *proxy, *proxyUser, *proxyPass, *proxyDomain, nil)
transport = &http.Transport{
Proxy: nil, // !!! IMPORTANT, do not set proxy here !!!
DialContext: ntlmDialContext,
}
} else {
transport = baseTransport
}
*/
}
// Create HTTP client with custom transport
client := &http.Client{
Transport: transport,
}
// Create the request
req, err := http.NewRequest("POST", *snowURL, bytes.NewBuffer([]byte(*payload)))
if err != nil {
log.Println("Error creating request:", err)
return
}
// Set headers
req.Header.Set("Content-Type", "application/json")
// Add Basic Authentication for target URL
if *snowUser != "" && *snowPass != "" {
basicAuth := base64.StdEncoding.EncodeToString([]byte(*snowUser + ":" + *snowPass))
req.Header.Set("Authorization", "Basic "+basicAuth)
}
// Send the request
resp, err := client.Do(req)
if err != nil {
log.Println("Error sending request:", err)
return
}
defer resp.Body.Close()
// Read response
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Println("Error reading response:", err)
return
}
// Print response
log.Println("Response Status:", resp.Status)
fmt.Println(string(body))
}