elastop

- Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.acid.vegas/-c.git
Log | Files | Refs | Archive | README | LICENSE

commit 273fed17767fc1d662574ed17d47ed090b652470
parent 4bbf0c6bf13626561270c16cce423794592dc507
Author: acidvegas <acid.vegas@acid.vegas>
Date: Fri, 13 Dec 2024 00:21:17 -0500

Added certificate based authentication option

Diffstat:
MREADME.md | 35+++++++++++++++++++++++++++++------
Melastop.go | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------

2 files changed, 88 insertions(+), 12 deletions(-)

diff --git a/README.md b/README.md
@@ -32,12 +32,35 @@ go build
 ```
 
 ### Command Line Flags
-| Flag        | Description            | Default       |
-| ----------- | ---------------------- | ------------- |
-| `-host`     | Elasticsearch host     | `localhost`   |
-| `-port`     | Elasticsearch port     | `9200`        |
-| `-user`     | Elasticsearch username | `elastic`     |
-| `-password` | Elasticsearch password | `ES_PASSWORD` |
+| Flag        | Description                           | Default       |
+| ----------- | ------------------------------------- | ------------- |
+| `-host`     | Elasticsearch host                    | `localhost`   |
+| `-port`     | Elasticsearch port                    | `9200`        |
+| `-user`     | Elasticsearch username                | `elastic`     |
+| `-password` | Elasticsearch password                | `ES_PASSWORD` |
+| `-apikey`   | Elasticsearch API key                 | `ES_API_KEY`  |
+| `-cert`     | Path to client certificate file       |               |
+| `-key`      | Path to client private key file       |               |
+| `-ca`       | Path to CA certificate file           |               |
+| `-insecure` | Skip TLS certificate verification     | `false`       |
+
+Note: Only one authentication method (username/password, API key, or certificates) can be used at a time.
+
+### Authentication Examples
+
+```bash
+# Using username/password
+./elastop -host https://elasticsearch.example.com -user elastic -password secret
+
+# Using API key
+./elastop -host https://elasticsearch.example.com -apikey your_api_key
+
+# Using certificate authentication
+./elastop -host https://elasticsearch.example.com -cert /path/to/client.crt -key /path/to/client.key -ca /path/to/ca.crt
+
+# Using certificate authentication with insecure SSL (not recommended for production)
+./elastop -host https://elasticsearch.example.com -cert /path/to/client.crt -key /path/to/client.key -insecure
+```
 
 ## Dashboard Layout
 
diff --git a/elastop.go b/elastop.go
@@ -2,6 +2,7 @@ package main
 
 import (
 	"crypto/tls"
+	"crypto/x509"
 	"encoding/json"
 	"flag"
 	"fmt"
@@ -537,6 +538,13 @@ func main() {
 	user := flag.String("user", os.Getenv("ES_USER"), "Elasticsearch username")
 	password := flag.String("password", os.Getenv("ES_PASSWORD"), "Elasticsearch password")
 	flag.StringVar(&apiKey, "apikey", os.Getenv("ES_API_KEY"), "Elasticsearch API key")
+
+	// Add new certificate-related flags
+	certFile := flag.String("cert", "", "Path to client certificate file")
+	keyFile := flag.String("key", "", "Path to client private key file")
+	caFile := flag.String("ca", "", "Path to CA certificate file")
+	skipVerify := flag.Bool("insecure", false, "Skip TLS certificate verification")
+
 	flag.Parse()
 
 	// Validate and process the host URL
@@ -545,20 +553,65 @@ func main() {
 		os.Exit(1)
 	}
 
-	// Validate authentication
-	if apiKey != "" && (*user != "" || *password != "") {
-		fmt.Fprintf(os.Stderr, "Error: Cannot use both API key and username/password authentication\n")
+	// Validate authentication methods - only one should be used
+	authMethods := 0
+	if apiKey != "" {
+		authMethods++
+	}
+	if *user != "" || *password != "" {
+		authMethods++
+	}
+	if *certFile != "" || *keyFile != "" {
+		authMethods++
+	}
+	if authMethods > 1 {
+		fmt.Fprintf(os.Stderr, "Error: Cannot use multiple authentication methods simultaneously (API key, username/password, or certificates)\n")
+		os.Exit(1)
+	}
+
+	// Validate certificate files if specified
+	if (*certFile != "" && *keyFile == "") || (*certFile == "" && *keyFile != "") {
+		fmt.Fprintf(os.Stderr, "Error: Both certificate and key files must be specified together\n")
 		os.Exit(1)
 	}
 
 	// Strip any trailing slash from the host
 	*host = strings.TrimRight(*host, "/")
 
+	// Create TLS config
+	tlsConfig := &tls.Config{
+		InsecureSkipVerify: *skipVerify,
+	}
+
+	// Load client certificates if specified
+	if *certFile != "" && *keyFile != "" {
+		cert, err := tls.LoadX509KeyPair(*certFile, *keyFile)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "Error loading client certificates: %v\n", err)
+			os.Exit(1)
+		}
+		tlsConfig.Certificates = []tls.Certificate{cert}
+	}
+
+	// Load CA certificate if specified
+	if *caFile != "" {
+		caCert, err := os.ReadFile(*caFile)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "Error reading CA certificate: %v\n", err)
+			os.Exit(1)
+		}
+
+		caCertPool := x509.NewCertPool()
+		if !caCertPool.AppendCertsFromPEM(caCert) {
+			fmt.Fprintf(os.Stderr, "Error parsing CA certificate\n")
+			os.Exit(1)
+		}
+		tlsConfig.RootCAs = caCertPool
+	}
+
 	// Create custom HTTP client with SSL configuration
 	tr := &http.Transport{
-		TLSClientConfig: &tls.Config{
-			InsecureSkipVerify: true, // Allow self-signed certificates
-		},
+		TLSClientConfig: tlsConfig,
 	}
 	client := &http.Client{
 		Transport: tr,