3 Commits
v1.0.5 ... main

Author SHA1 Message Date
273fed1776 Added certificate based authentication option 2024-12-13 00:21:17 -05:00
4bbf0c6bf1 Allow no auth connections 2024-12-09 15:30:18 -05:00
23a7c216ab Added missing spacer between 'Uptime' and 'OS' 2024-12-06 12:31:57 -05:00
4 changed files with 88 additions and 16 deletions

1
.gitignore vendored
View File

@@ -4,6 +4,7 @@
*.dll
*.so
*.dylib
elastop
# Test binary, built with `go test -c`
*.test

View File

@@ -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

BIN
elastop

Binary file not shown.

View File

@@ -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,25 +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)
}
if apiKey == "" && (*user == "" || *password == "") {
fmt.Fprintf(os.Stderr, "Error: Must provide either API key or both username and password\n")
// 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,
@@ -619,7 +667,7 @@ func main() {
// Set authentication
if apiKey != "" {
req.Header.Set("Authorization", fmt.Sprintf("ApiKey %s", apiKey))
} else {
} else if *user != "" && *password != "" {
req.SetBasicAuth(*user, *password)
}
@@ -1213,7 +1261,7 @@ func getMaxLengths(nodesInfo NodesInfo, indicesStats IndexStats) (int, int, int,
}
func getNodesPanelHeader(maxNodeNameLen, maxTransportLen int) string {
return fmt.Sprintf("[::b]%-*s [#444444]│[#00ffff] %-13s [#444444]│[#00ffff] %*s [#444444]│[#00ffff] %-7s [#444444]│[#00ffff] %-9s [#444444]│[#00ffff] %-16s [#444444]│[#00ffff] %-16s [#444444]│[#00ffff] %-16s [#444444]│[#00ffff] %-6s [#444444][#00ffff] %-25s[white]\n",
return fmt.Sprintf("[::b]%-*s [#444444]│[#00ffff] %-13s [#444444]│[#00ffff] %*s [#444444]│[#00ffff] %-7s [#444444]│[#00ffff] %-9s [#444444]│[#00ffff] %-16s [#444444]│[#00ffff] %-16s [#444444]│[#00ffff] %-16s [#444444]│[#00ffff] %-6s [#444444][#00ffff] %-25s[white]\n",
maxNodeNameLen,
"Node Name",
"Roles",