From 33ed528afe11ac3193f004d300a65cd08031857e Mon Sep 17 00:00:00 2001 From: Toni Moreno Date: Tue, 15 Nov 2016 16:52:24 +0100 Subject: [PATCH] Apache input enhancements ( added Basic Auth and SSL skipverify ) (#1964) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * added connection Timeout parĂ¡meter, basic HTTP autentication and HTTP support with Sslskipverify option * updated README.md * added optional SSL config , changed timeout name and type , and other minor fixes * added some code style improvements * Update README.md --- plugins/inputs/apache/README.md | 10 +++++ plugins/inputs/apache/apache.go | 77 ++++++++++++++++++++++++++++----- 2 files changed, 75 insertions(+), 12 deletions(-) diff --git a/plugins/inputs/apache/README.md b/plugins/inputs/apache/README.md index 60a4783d2..b700a1b44 100644 --- a/plugins/inputs/apache/README.md +++ b/plugins/inputs/apache/README.md @@ -2,6 +2,16 @@ #### Plugin arguments: - **urls** []string: List of apache-status URLs to collect from. Default is "http://localhost/server-status?auto". +- **username** string: Username for HTTP basic authentication +- **password** string: Password for HTTP basic authentication +- **timeout** duration: time that the HTTP connection will remain waiting for response. Defalt 4 seconds ("4s") + +##### Optional SSL Config + +- **ssl_ca** string: the full path for the SSL CA certicate +- **ssl_cert** string: the full path for the SSL certificate +- **ssl_key** string: the full path for the key file +- **insecure_skip_verify** bool: if true HTTP client will skip all SSL verifications related to peer and host. Default to false #### Description diff --git a/plugins/inputs/apache/apache.go b/plugins/inputs/apache/apache.go index be891bb31..85e7ee4d9 100644 --- a/plugins/inputs/apache/apache.go +++ b/plugins/inputs/apache/apache.go @@ -11,17 +11,42 @@ import ( "time" "github.com/influxdata/telegraf" + "github.com/influxdata/telegraf/internal" "github.com/influxdata/telegraf/plugins/inputs" ) type Apache struct { - Urls []string + Urls []string + Username string + Password string + ResponseTimeout internal.Duration + // Path to CA file + SSLCA string `toml:"ssl_ca"` + // Path to host cert file + SSLCert string `toml:"ssl_cert"` + // Path to cert key file + SSLKey string `toml:"ssl_key"` + // Use SSL but skip chain & host verification + InsecureSkipVerify bool } var sampleConfig = ` ## An array of Apache status URI to gather stats. ## Default is "http://localhost/server-status?auto". urls = ["http://localhost/server-status?auto"] + ## user credentials for basic HTTP authentication + username = "myuser" + password = "mypassword" + + ## Timeout to the complete conection and reponse time in seconds + response_timeout = "25s" ## default to 5 seconds + + ## Optional SSL Config + # ssl_ca = "/etc/telegraf/ca.pem" + # ssl_cert = "/etc/telegraf/cert.pem" + # ssl_key = "/etc/telegraf/key.pem" + ## Use SSL but skip chain & host verification + # insecure_skip_verify = false ` func (n *Apache) SampleConfig() string { @@ -36,6 +61,9 @@ func (n *Apache) Gather(acc telegraf.Accumulator) error { if len(n.Urls) == 0 { n.Urls = []string{"http://localhost/server-status?auto"} } + if n.ResponseTimeout.Duration < time.Second { + n.ResponseTimeout.Duration = time.Second * 5 + } var outerr error var errch = make(chan error) @@ -61,21 +89,46 @@ func (n *Apache) Gather(acc telegraf.Accumulator) error { return outerr } -var tr = &http.Transport{ - ResponseHeaderTimeout: time.Duration(3 * time.Second), -} - -var client = &http.Client{ - Transport: tr, - Timeout: time.Duration(4 * time.Second), -} - func (n *Apache) gatherUrl(addr *url.URL, acc telegraf.Accumulator) error { - resp, err := client.Get(addr.String()) + + var tr *http.Transport + + if addr.Scheme == "https" { + tlsCfg, err := internal.GetTLSConfig( + n.SSLCert, n.SSLKey, n.SSLCA, n.InsecureSkipVerify) + if err != nil { + return err + } + tr = &http.Transport{ + ResponseHeaderTimeout: time.Duration(3 * time.Second), + TLSClientConfig: tlsCfg, + } + } else { + tr = &http.Transport{ + ResponseHeaderTimeout: time.Duration(3 * time.Second), + } + } + + client := &http.Client{ + Transport: tr, + Timeout: n.ResponseTimeout.Duration, + } + + req, err := http.NewRequest("GET", addr.String(), nil) if err != nil { - return fmt.Errorf("error making HTTP request to %s: %s", addr.String(), err) + return fmt.Errorf("error on new request to %s : %s\n", addr.String(), err) + } + + if len(n.Username) != 0 && len(n.Password) != 0 { + req.SetBasicAuth(n.Username, n.Password) + } + + resp, err := client.Do(req) + if err != nil { + return fmt.Errorf("error on request to %s : %s\n", addr.String(), err) } defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { return fmt.Errorf("%s returned HTTP status %s", addr.String(), resp.Status) }