diff --git a/docs/apis/url.md b/docs/apis/url.md index 7c7f5869..1233828a 100644 --- a/docs/apis/url.md +++ b/docs/apis/url.md @@ -1,17 +1,17 @@ # url API -The `url` API allows you to retrieve information from an HTTP endpoint. +The `url` API allows you to retrieve information from an HTTP endpoint. -* [Basic usage](#Basicusage) -* [Use POST/PUT methods with a body](#UsePOSTPUTmethodswithabody) -* [Configure your HTTPS connections](#ConfigureyourHTTPSconnections) -* [Specify a common base URL](#SpecifyacommonbaseURL) -* [URL with cache for later processing](#URLwithcacheforlaterprocessing) -* [Include response headers on sample](#ReturnResponseHeaders) +- [Basic usage](#Basicusage) +- [Use POST/PUT methods with a body](#UsePOSTPUTmethodswithabody) +- [Configure your HTTPS connections](#ConfigureyourHTTPSconnections) +- [Specify a common base URL](#SpecifyacommonbaseURL) +- [URL with cache for later processing](#URLwithcacheforlaterprocessing) +- [Include response headers on sample](#ReturnResponseHeaders) -## Basic usage +## Basic usage -```yaml +```yaml name: example apis: - event_type: ExampleSample @@ -22,29 +22,31 @@ apis: The above Flex configuration retrieves a JSON file containing a set of metrics from the provided URL. Note that the `url` key can be followed by a `headers` section, which allows specifying HTTP headers. -## Use POST/PUT methods with a body +## Use POST/PUT methods with a body To specify a `POST` or `PUT` request with a body, use the `method` and `payload` properties. ```yaml -name: httpPostExample -apis: +name: httpPostExample +apis: - name: httpPost url: https://jsonplaceholder.typicode.com/posts method: POST - payload: > + payload: > {"title": "foo","body": "bar","userId": 1} ``` -## Configure your HTTPS connections +## Configure your HTTPS connections When using TLS endpoints with self-signed certificates, define a `tls_config` section with any of the following items: -| Name | Type | Default | Description | -|---:|:---:|:---:|---| -| `enable` | bool | `false` | Set to `true` to enable custom TLS configuration. Requires `ca` to be defined if enabled. | -| `insecure_skip_verify` | bool | `false` | Set to `true` to skip the verification of TLS certificates. | -| `ca` | string | _Empty_ | The Certificate Authority PEM certificate, in case your HTTPS endpoint has self-signed certificates. | +| Name | Type | Default | Description | +| ---------------------: | :----: | :-----: | ------------------------------------------------------------------------------------------------------------ | +| `enable` | bool | `false` | Set to `true` to enable custom TLS configuration. Requires `ca` to be defined if enabled. | +| `insecure_skip_verify` | bool | `false` | Set to `true` to skip the verification of TLS certificates. | +| `ca` | string | _Empty_ | The Certificate Authority PEM certificate, in case your HTTPS endpoint has self-signed certificates. | +| `cert` | string | _Empty_ | PEM encoded certificate (must be used with `key`), in case your HTTPS endpoint has self-signed certificates. | +| `key` | string | _Empty_ | PEM encoded key (must be used with `cert`), in case your HTTPS endpoint has self-signed certificates. | ### TLS configuration example: @@ -60,18 +62,18 @@ apis: ca: /etc/bundles/my-ca-cert.pem ``` -## Specify a common base URL +## Specify a common base URL When you have to query several different URLs, specifying a `base_url` under `global` can be quite helpful, as it allows you to provide URL path segment in `url` fields instead of full URLs. -### Base URL example +### Base URL example ```yaml name: consulFlex global: - base_url: http://consul-host/v1/ - headers: - X-Consul-Token: my-root-consul-token + base_url: http://consul-host/v1/ + headers: + X-Consul-Token: my-root-consul-token apis: - event_type: ConsulHealthSample url: health/service/consul @@ -81,7 +83,7 @@ apis: url: agent/members ``` -## URL with cache for later processing +## URL with cache for later processing URL invocations are cached to avoid having to query them repeatedly. Use `cache` under `command` to read cached data. @@ -101,42 +103,52 @@ apis: - expression: Active connections:\s(\S+) keys: [net.connectionsActive] - expression: \s?(\d+)\s(\d+)\s(\d+) - keys: [net.connectionsAcceptedPerSecond, net.handledPerSecond, net.requestsPerSecond] + keys: + [ + net.connectionsAcceptedPerSecond, + net.handledPerSecond, + net.requestsPerSecond, + ] - expression: Reading:\s(\d+)\s\S+\s(\d+)\s\S+\s(\d+) - keys: [net.connectionsReading, net.connectionsWriting, net.connectionsWaiting] + keys: + [ + net.connectionsReading, + net.connectionsWriting, + net.connectionsWaiting, + ] math: net.connectionsDroppedPerSecond: ${net.connectionsAcceptedPerSecond} - ${net.handledPerSecond} ``` -## Include response headers on sample +## Include response headers on sample To include response headers on the metric sample set `return_headers` attribute to true. -### Return headers example +### Return headers example ```yaml name: example apis: - name: ExampleSample url: https://my-host:8443/admin/metrics/1 - return_headers: true + return_headers: true ``` Given the following output for each metric: ```json { - "event_type": "ExampleSample", - "integration_name": "com.newrelic.nri-flex", - "integration_version": "version-number", - "id": 1, - "completed": "true", - "api.StatusCode": 200, - "api.header.Access-Control-Allow-Credentials": "[true]", - "api.header.Age": "[4459]", - "api.header.Content-Type": "[application/json; charset=utf-8]", - "api.header.Date": "[Mon, 25 May 2020 16:23:53 GMT]", - "api.header.Expires": "[-1]", - "api.header.Retry-Count": "[0]" + "event_type": "ExampleSample", + "integration_name": "com.newrelic.nri-flex", + "integration_version": "version-number", + "id": 1, + "completed": "true", + "api.StatusCode": 200, + "api.header.Access-Control-Allow-Credentials": "[true]", + "api.header.Age": "[4459]", + "api.header.Content-Type": "[application/json; charset=utf-8]", + "api.header.Date": "[Mon, 25 May 2020 16:23:53 GMT]", + "api.header.Expires": "[-1]", + "api.header.Retry-Count": "[0]" } -``` +``` diff --git a/internal/inputs/http.go b/internal/inputs/http.go index 5f1f0f4d..0d705221 100644 --- a/internal/inputs/http.go +++ b/internal/inputs/http.go @@ -242,6 +242,15 @@ func setRequestOptions(request *gorequest.SuperAgent, yml load.Config, api load. } } + if yml.Global.TLSConfig.Key != "" && yml.Global.TLSConfig.Cert != "" { + cert, err := tls.LoadX509KeyPair(yml.Global.TLSConfig.Cert, yml.Global.TLSConfig.Key) + if err != nil { + load.Logrus.WithError(err).Error("http: failed to load x509 keypair") + } else { + tmpGlobalTLSConfig.Certificates = []tls.Certificate{cert} + } + } + request = request.TLSClientConfig(&tmpGlobalTLSConfig) if api.TLSConfig.Enable { @@ -260,6 +269,16 @@ func setRequestOptions(request *gorequest.SuperAgent, yml load.Config, api load. tmpAPITLSConfig.RootCAs = rootCAs } } + + if api.TLSConfig.Key != "" && api.TLSConfig.Cert != "" { + cert, err := tls.LoadX509KeyPair(api.TLSConfig.Cert, api.TLSConfig.Key) + if err != nil { + load.Logrus.WithError(err).Error("http: failed to load x509 keypair") + } else { + tmpAPITLSConfig.Certificates = []tls.Certificate{cert} + } + } + request = request.TLSClientConfig(&tmpAPITLSConfig) } diff --git a/internal/load/load.go b/internal/load/load.go index d4dbf5c2..778ff57d 100644 --- a/internal/load/load.go +++ b/internal/load/load.go @@ -238,7 +238,9 @@ type TLSConfig struct { InsecureSkipVerify bool `yaml:"insecure_skip_verify"` MinVersion uint16 `yaml:"min_version"` MaxVersion uint16 `yaml:"max_version"` - Ca string `yaml:"ca"` // path to ca to read + Ca string `yaml:"ca"` // path to ca to read + Key string `yaml:"key"` // path to key to read + Cert string `yaml:"cert"` // path to cert to read } // SampleMerge merge multiple samples into one (will remove previous samples)