From 34487bbdac48397cb6e34d1a4fe14af42aafdb81 Mon Sep 17 00:00:00 2001 From: SP Kesan Date: Thu, 28 Jan 2021 03:18:39 +0530 Subject: [PATCH] Enhancements (#41) - [TOOLS-1614] - Fetch credentials and certificates via file, environment variables and in base64 encoded form - Added new XDR (per DC) metric nodes --- ape.toml | 40 ++++++++++++---- ape.toml.template | 40 ++++++++++++---- common.go | 116 +++++++++++++++++++++++++++++++++------------- go.mod | 10 ++-- go.sum | 21 +++++---- main.go | 18 ++++++- observer.go | 49 ++++++++++++++------ watcher_xdr.go | 1 + 8 files changed, 217 insertions(+), 78 deletions(-) diff --git a/ape.toml b/ape.toml index 2b5cfc3d..455b4361 100644 --- a/ape.toml +++ b/ape.toml @@ -21,6 +21,12 @@ log_file = "" log_level = "" # Basic HTTP authentication for '/metrics'. +# Supports below formats, +# 1. Credential directly - "" +# 2. Credential via file - "file:" +# 3. Credential via environment variable - "env:" +# 4. Credential via environment variable containing base64 encoded credential - "env-b64:" +# 5. Credential in base64 encoded form - "b64:" basic_auth_username="" basic_auth_password="" @@ -28,6 +34,16 @@ basic_auth_password="" db_host="localhost" db_port=3000 +# TLS certificates. +# Supports below formats, +# 2. Certificate file path - "file:" +# 3. Environment variable containing base64 encoded certificate - "env-b64:" +# 4. Base64 encoded certificate - "b64:" +# Applicable to 'root_ca', 'cert_file' and 'key_file' configurations. + +# root certificate file +root_ca="" + # certificate file cert_file="" @@ -35,19 +51,24 @@ cert_file="" key_file="" # Passphrase for encrypted key_file. Supports below formats, -# 1. Passphrase directly - "" -# 2. Passphrase via file - "file:" -# 3. Passphrase via environment variable - "env:" +# 1. Passphrase directly - "" +# 2. Passphrase via file - "file:" +# 3. Passphrase via environment variable - "env:" +# 4. Passphrase via environment variable containing base64 encoded passphrase - "env-b64:" +# 5. Passphrase in base64 encoded form - "b64:" key_file_passphrase="" # node TLS name for authentication node_tls_name="" -# root certificate file -root_ca="" - -# authentication mode: internal (for server), external (LDAP, etc.) -auth_mode="" +# Aerospike cluster security credentials. +# Supports below formats, +# 1. Credential directly - "" +# 2. Credential via file - "file:" +# 3. Credential via environment variable - "env:" +# 4. Credential via environment variable containing base64 encoded credential - "env-b64:" +# 5. Credential in base64 encoded form - "b64:" +# Applicable to 'user' and 'password' configurations. # database user user="" @@ -55,6 +76,9 @@ user="" # database password password="" +# authentication mode: internal (for server), external (LDAP, etc.) +auth_mode="" + # timeout for sending commands to the server node in seconds timeout=5 diff --git a/ape.toml.template b/ape.toml.template index c4ec5af7..21341105 100644 --- a/ape.toml.template +++ b/ape.toml.template @@ -21,6 +21,12 @@ log_file = "${AGENT_LOG_FILE}" log_level = "${AGENT_LOG_LEVEL}" # Basic HTTP authentication for '/metrics'. +# Supports below formats, +# 1. Credential directly - "" +# 2. Credential via file - "file:" +# 3. Credential via environment variable - "env:" +# 4. Credential via environment variable containing base64 encoded credential - "env-b64:" +# 5. Credential in base64 encoded form - "b64:" basic_auth_username="${BASIC_AUTH_USERNAME}" basic_auth_password="${BASIC_AUTH_PASSWORD}" @@ -28,6 +34,16 @@ basic_auth_password="${BASIC_AUTH_PASSWORD}" db_host="${AS_HOST}" db_port=${AS_PORT} +# TLS certificates. +# Supports below formats, +# 2. Certificate file path - "file:" +# 3. Environment variable containing base64 encoded certificate - "env-b64:" +# 4. Base64 encoded certificate - "b64:" +# Applicable to 'root_ca', 'cert_file' and 'key_file' configurations. + +# root certificate file +root_ca="${AS_ROOT_CA}" + # certificate file cert_file="${AS_CERT_FILE}" @@ -35,19 +51,24 @@ cert_file="${AS_CERT_FILE}" key_file="${AS_KEY_FILE}" # Passphrase for encrypted key_file. Supports below formats, -# 1. Passphrase directly - "" -# 2. Passphrase via file - "file:" -# 3. Passphrase via environment variable - "env:" +# 1. Passphrase directly - "" +# 2. Passphrase via file - "file:" +# 3. Passphrase via environment variable - "env:" +# 4. Passphrase via environment variable containing base64 encoded passphrase - "env-b64:" +# 5. Passphrase in base64 encoded form - "b64:" key_file_passphrase="${AS_KEY_FILE_PASSPHRASE}" # node TLS name for authentication node_tls_name="${AS_NODE_TLS_NAME}" -# root certificate file -root_ca="${AS_ROOT_CA}" - -# authentication mode: internal (for server), external (LDAP, etc.) -auth_mode="${AS_AUTH_MODE}" +# Aerospike cluster security credentials. +# Supports below formats, +# 1. Credential directly - "" +# 2. Credential via file - "file:" +# 3. Credential via environment variable - "env:" +# 4. Credential via environment variable containing base64 encoded credential - "env-b64:" +# 5. Credential in base64 encoded form - "b64:" +# Applicable to 'user' and 'password' configurations. # database user user="${AS_AUTH_USER}" @@ -55,6 +76,9 @@ user="${AS_AUTH_USER}" # database password password="${AS_AUTH_PASSWORD}" +# authentication mode: internal (for server), external (LDAP, etc.) +auth_mode="${AS_AUTH_MODE}" + # timeout for sending commands to the server node in seconds timeout=${TICKER_TIMEOUT} diff --git a/common.go b/common.go index 7f184962..b6c50b7f 100644 --- a/common.go +++ b/common.go @@ -3,7 +3,7 @@ package main import ( "bytes" "crypto/subtle" - "errors" + "encoding/base64" "fmt" "io/ioutil" "net/http" @@ -16,8 +16,6 @@ import ( "github.com/gobwas/glob" "github.com/jameskeane/bcrypt" "github.com/prometheus/client_golang/prometheus" - - log "github.com/sirupsen/logrus" ) func makeMetric(namespace, name string, t metricType, constLabels map[string]string, labels ...string) promMetric { @@ -103,7 +101,7 @@ func hashPassword(password string) ([]byte, error) { // Check HTTP Basic Authentication. // Validate username, password from the http request against the configured values. -func validateBasicAuth(_ http.ResponseWriter, r *http.Request, username string, password string) bool { +func validateBasicAuth(r *http.Request, username string, password string) bool { user, pass, ok := r.BasicAuth() if !ok || subtle.ConstantTimeCompare([]byte(user), []byte(username)) != 1 || subtle.ConstantTimeCompare([]byte(pass), []byte(password)) != 1 { @@ -173,48 +171,102 @@ func filterBlockedMetrics(filteredMetrics map[string]metricType, blocklist []str } } -// Get key file passphrase from environment variable or from a file or directly from the config variable -// keyFilePassphraseConfig can be one of the following, -// 1. "" -// 2. "file:" -// 3. "env:" -func getKeyFilePassphrase(keyFilePassphraseConfig string) ([]byte, error) { - keyFilePassphraseSource := strings.SplitN(keyFilePassphraseConfig, ":", 2) - - if len(keyFilePassphraseSource) == 2 { - if keyFilePassphraseSource[0] == "file" { - dataBytes, err := ioutil.ReadFile(keyFilePassphraseSource[1]) - if err != nil { - return nil, err +// Get secret +// secretConfig can be one of the following, +// 1. "" (secret directly) +// 2. "file:" (file containing secret) +// 3. "env:" (environment variable containing secret) +// 4. "env-b64:" (environment variable containing base64 encoded secret) +// 5. "b64:" (base64 encoded secret) +func getSecret(secretConfig string) ([]byte, error) { + secretSource := strings.SplitN(secretConfig, ":", 2) + + if len(secretSource) == 2 { + switch secretSource[0] { + case "file": + return readFromFile(secretSource[1]) + + case "env": + secret, ok := os.LookupEnv(secretSource[1]) + if !ok { + return nil, fmt.Errorf("Environment variable %s not set", secretSource[1]) } - keyPassphrase := bytes.TrimSuffix(dataBytes, []byte("\n")) + return []byte(secret), nil + + case "env-b64": + return getValueFromBase64EnvVar(secretSource[1]) - return keyPassphrase, nil + case "b64": + return getValueFromBase64(secretSource[1]) + + default: + return nil, fmt.Errorf("Invalid source: %s", secretSource[0]) } + } - if keyFilePassphraseSource[0] == "env" { - keyPassphrase, ok := os.LookupEnv(keyFilePassphraseSource[1]) - if !ok { - return nil, errors.New("Environment variable " + keyFilePassphraseSource[1] + " not set") - } + return []byte(secretConfig), nil +} + +// Get certificate +// certConfig can be one of the following, +// 1. "" (certificate file path directly) +// 2. "file:" (certificate file path) +// 3. "env-b64:" (environment variable containing base64 encoded certificate) +// 4. "b64:" (base64 encoded certificate) +func getCertificate(certConfig string) ([]byte, error) { + certificateSource := strings.SplitN(certConfig, ":", 2) + + if len(certificateSource) == 2 { + switch certificateSource[0] { + case "file": + return readFromFile(certificateSource[1]) + + case "env-b64": + return getValueFromBase64EnvVar(certificateSource[1]) - return []byte(keyPassphrase), nil + case "b64": + return getValueFromBase64(certificateSource[1]) + + default: + return nil, fmt.Errorf("Invalid source %s", certificateSource[0]) } } - return []byte(keyFilePassphraseConfig), nil + // Assume certConfig is a file path (backward compatible) + return readFromFile(certConfig) +} + +// Read content from file +func readFromFile(filePath string) ([]byte, error) { + dataBytes, err := ioutil.ReadFile(filePath) + if err != nil { + return nil, fmt.Errorf("Failed to read from file `%s`: `%v`", filePath, err) + } + + data := bytes.TrimSuffix(dataBytes, []byte("\n")) + + return data, nil +} + +// Get decoded base64 value from environment variable +func getValueFromBase64EnvVar(envVar string) ([]byte, error) { + b64Value, ok := os.LookupEnv(envVar) + if !ok { + return nil, fmt.Errorf("Environment variable %s not set", envVar) + } + + return getValueFromBase64(b64Value) } -// Read certificate file and abort if any errors -// Returns file content as byte array -func readCertFile(filename string) []byte { - dataBytes, err := ioutil.ReadFile(filename) +// Get decoded base64 value +func getValueFromBase64(b64Value string) ([]byte, error) { + value, err := base64.StdEncoding.DecodeString(b64Value) if err != nil { - log.Fatalf("Failed to read certificate or key file `%s` : `%s`", filename, err) + return nil, fmt.Errorf("Failed to decode base64 value: %v", err) } - return dataBytes + return value, nil } func sanitizeUTF8(lv string) string { diff --git a/go.mod b/go.mod index 9450e587..b8e700ea 100644 --- a/go.mod +++ b/go.mod @@ -4,17 +4,17 @@ go 1.14 require ( github.com/BurntSushi/toml v0.3.1 - github.com/aerospike/aerospike-client-go v3.1.1+incompatible + github.com/aerospike/aerospike-client-go v4.1.0+incompatible github.com/gobwas/glob v0.2.3 github.com/hashicorp/go-version v1.2.1 github.com/jameskeane/bcrypt v0.0.0-20120420032655-c3cd44c1e20f github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/onsi/ginkgo v1.14.0 // indirect - github.com/prometheus/client_golang v1.8.0 - github.com/prometheus/common v0.15.0 // indirect + github.com/prometheus/client_golang v1.9.0 + github.com/prometheus/procfs v0.3.0 // indirect github.com/sirupsen/logrus v1.7.0 github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da // indirect - golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 // indirect - golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect + golang.org/x/sync v0.0.0-20201207232520-09787c993a3a // indirect + golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c // indirect google.golang.org/protobuf v1.25.0 // indirect ) diff --git a/go.sum b/go.sum index 3123b3bb..29fbf77f 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/aerospike/aerospike-client-go v3.1.1+incompatible h1:+zAuvKMI9rq/hdpwX8srmFvDKfprMPX1SQGMLkBpvuc= -github.com/aerospike/aerospike-client-go v3.1.1+incompatible/go.mod h1:zj8LBEnWBDOVEIJt8LvaRvDG5ARAoa5dBeHaB472NRc= +github.com/aerospike/aerospike-client-go v4.1.0+incompatible h1:s8l82c619XS2aps02MU5I3o3GofeIOeWfeKCoVq+1Zs= +github.com/aerospike/aerospike-client-go v4.1.0+incompatible/go.mod h1:zj8LBEnWBDOVEIJt8LvaRvDG5ARAoa5dBeHaB472NRc= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -241,8 +241,8 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.8.0 h1:zvJNkoCFAnYFNC24FV8nW4JdRJ3GIFcLbg65lL/JDcw= -github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM= +github.com/prometheus/client_golang v1.9.0 h1:Rrch9mh17XcxvEu9D9DEpb4isxjGBtcevQjKvxPRQIU= +github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= @@ -257,7 +257,6 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.15.0 h1:4fgOnadei3EZvgRwxJ7RMpG1k1pOZth5Pc13tyspaKM= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -268,6 +267,8 @@ github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFB github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.3.0 h1:Uehi/mxLK0eiUc0H0++5tpMGTexB8wZ598MIgU8VpDM= +github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -361,8 +362,8 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -391,9 +392,9 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= diff --git a/main.go b/main.go index d7bcd64d..a420b791 100644 --- a/main.go +++ b/main.go @@ -61,10 +61,24 @@ func main() { mux := http.NewServeMux() + // Get http basic auth username + httpBasicAuthUsernameBytes, err := getSecret(config.AeroProm.BasicAuthUsername) + if err != nil { + log.Fatal(err) + } + httpBasicAuthUsername := string(httpBasicAuthUsernameBytes) + + // Get http basic auth password + httpBasicAuthPasswordBytes, err := getSecret(config.AeroProm.BasicAuthPassword) + if err != nil { + log.Fatal(err) + } + httpBasicAuthPassword := string(httpBasicAuthPasswordBytes) + // Handle "/metrics" url mux.HandleFunc("/metrics", func(w http.ResponseWriter, r *http.Request) { - if config.AeroProm.BasicAuthUsername != "" { - if validateBasicAuth(w, r, config.AeroProm.BasicAuthUsername, config.AeroProm.BasicAuthPassword) { + if httpBasicAuthUsername != "" { + if validateBasicAuth(r, httpBasicAuthUsername, httpBasicAuthPassword) { promhttp.HandlerFor(promReg, promhttp.HandlerOpts{}).ServeHTTP(w, r) return } diff --git a/observer.go b/observer.go index 573cae94..2d4b7683 100644 --- a/observer.go +++ b/observer.go @@ -54,32 +54,43 @@ func initTLS() *tls.Config { if len(config.Aerospike.RootCA) > 0 { // Try to load system CA certs and add them to the system cert pool - caCert := readCertFile(config.Aerospike.RootCA) + caCert, err := getCertificate(config.Aerospike.RootCA) + if err != nil { + log.Fatal(err) + } - log.Debugf("Adding server certificate `%s` to the pool...", config.Aerospike.RootCA) + log.Debugf("Adding CA certificate to the pool...") serverPool.AppendCertsFromPEM(caCert) } var clientPool []tls.Certificate if len(config.Aerospike.CertFile) > 0 || len(config.Aerospike.KeyFile) > 0 { - // Read Cert and Key files - certFileBytes := readCertFile(config.Aerospike.CertFile) - keyFileBytes := readCertFile(config.Aerospike.KeyFile) + // Read cert file + certFileBytes, err := getCertificate(config.Aerospike.CertFile) + if err != nil { + log.Fatal(err) + } + + // Read key file + keyFileBytes, err := getCertificate(config.Aerospike.KeyFile) + if err != nil { + log.Fatal(err) + } // Decode PEM data keyBlock, _ := pem.Decode(keyFileBytes) certBlock, _ := pem.Decode(certFileBytes) if keyBlock == nil || certBlock == nil { - log.Fatalf("Unable to decode PEM data for `%s` or `%s`", config.Aerospike.KeyFile, config.Aerospike.CertFile) + log.Fatalf("Failed to decode PEM data for key or certificate") } // Check and Decrypt the the Key Block using passphrase if x509.IsEncryptedPEMBlock(keyBlock) { - keyFilePassphraseBytes, err := getKeyFilePassphrase(config.Aerospike.KeyFilePassphrase) + keyFilePassphraseBytes, err := getSecret(config.Aerospike.KeyFilePassphrase) if err != nil { - log.Fatalf("Failed to get Key file passphrase for `%s` : `%s`", config.Aerospike.KeyFile, err) + log.Fatalf("Failed to get key passphrase: `%s`", err) } decryptedDERBytes, err := x509.DecryptPEMBlock(keyBlock, keyFilePassphraseBytes) @@ -96,16 +107,16 @@ func initTLS() *tls.Config { certPEM := pem.EncodeToMemory(certBlock) if keyPEM == nil || certPEM == nil { - log.Fatalf("Unable to encode PEM data for `%s` or `%s`", config.Aerospike.KeyFile, config.Aerospike.CertFile) + log.Fatalf("Failed to encode PEM data for key or certificate") } cert, err := tls.X509KeyPair(certPEM, keyPEM) if err != nil { - log.Fatalf("FAILED: Adding client certificate `%s` and key file `%s` to the pool failed: `%s`", config.Aerospike.CertFile, config.Aerospike.KeyFile, err) + log.Fatalf("Failed to add client certificate and key to the pool: `%s`", err) } - log.Debugf("Adding client certificate `%s` to the pool...\n", config.Aerospike.CertFile) + log.Debugf("Adding client certificate and key to the pool...") clientPool = append(clientPool, cert) } @@ -135,9 +146,21 @@ func newObserver(server *aero.Host, user, pass string) (o *Observer, err error) log.Fatalln("Invalid auth mode: only `internal` and `external` values are accepted.") } + // Get aerospike auth username + username, err := getSecret(user) + if err != nil { + log.Fatal(err) + } + + // Get aerospike auth password + password, err := getSecret(pass) + if err != nil { + log.Fatal(err) + } + clientPolicy := aero.NewClientPolicy() - clientPolicy.User = user - clientPolicy.Password = pass + clientPolicy.User = string(username) + clientPolicy.Password = string(password) if authMode == "external" { clientPolicy.AuthMode = aero.AuthModeExternal } diff --git a/watcher_xdr.go b/watcher_xdr.go index c027b6fc..0e6a7f6a 100644 --- a/watcher_xdr.go +++ b/watcher_xdr.go @@ -19,6 +19,7 @@ var xdrRawMetrics = map[string]metricType{ "throughput": mtGauge, "latency_ms": mtGauge, "lap_us": mtGauge, + "nodes": mtGauge, "success": mtCounter, "abandoned": mtCounter, "not_found": mtCounter,