Skip to content

Commit 47286d7

Browse files
committed
respect the NO_PROXY environment variable (#551)
also, use stdlib functions to get the proxy url fixes #458 closes #551
1 parent 8f6b2b8 commit 47286d7

File tree

7 files changed

+77
-25
lines changed

7 files changed

+77
-25
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,14 @@
33
## Unreleased
44
[Check the diff](https://github.com/elastic/apm-agent-python/compare/v5.0.0...master)
55

6+
### Security issues
7+
8+
* This release fixes CVE-2019-7617
9+
610
### New Features
711

812
* added support for global labels which will be applied to every transaction/error/metric (#549)
13+
* added support for `NO_PROXY` environment variable (#458, #551)
914

1015
### Bugfixes
1116

docs/api.asciidoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ client.capture_message('Billing process succeeded.')
7373
* `message`: The message as a string.
7474
* `param_message`: Alternatively, a parameterized message as a dictionary.
7575
The dictionary contains two values: `message`, and `params`.
76-
This allows the APM server to group messages together that share the same
76+
This allows the APM Server to group messages together that share the same
7777
parameterized message. Example:
7878
+
7979
[source,python]

docs/configuration.asciidoc

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ The URL must be fully qualified, including protocol (`http` or `https`) and port
111111
|============
112112

113113

114-
The transport class to use when sending events to the APM server.
114+
The transport class to use when sending events to the APM Server.
115115
The default `AsyncTransport` uses a background thread to send data.
116116
If your environment doesn't allow background threads, you can use
117117
`elasticapm.transport.http.Transport` instead.
@@ -152,16 +152,16 @@ You must use the query bar to filter for a specific environment in versions prio
152152
| `ELASTIC_APM_SECRET_TOKEN` | `SECRET_TOKEN` | `None` | A random string
153153
|============
154154

155-
This string is used to ensure that only your agents can send data to your APM server.
156-
Both the agents and the APM server have to be configured with the same secret token.
155+
This string is used to ensure that only your agents can send data to your APM Server.
156+
Both the agents and the APM Server have to be configured with the same secret token.
157157
One example to generate a secure secret token is:
158158

159159
[source,bash]
160160
----
161161
python -c "import uuid; print(str(uuid.uuid4()))"
162162
----
163163

164-
WARNING: secret tokens only provide any security if your APM server use TLS.
164+
WARNING: secret tokens only provide any security if your APM Server use TLS.
165165

166166
[float]
167167
[[config-service-version]]
@@ -214,7 +214,7 @@ otherwise, the default is `None`.
214214
|============
215215

216216
A list of exception types to be filtered.
217-
Exceptions of these types will not be sent to the APM server.
217+
Exceptions of these types will not be sent to the APM Server.
218218

219219

220220
[float]
@@ -228,7 +228,7 @@ Exceptions of these types will not be sent to the APM server.
228228
|============
229229

230230
A list of regular expressions.
231-
Transactions that match any of the of the configured patterns will be ignored and not sent to the APM server.
231+
Transactions that match any of the of the configured patterns will be ignored and not sent to the APM Server.
232232

233233

234234
[float]
@@ -243,12 +243,12 @@ Transactions that match any of the of the configured patterns will be ignored an
243243

244244
A timeout for requests to the APM Server.
245245
The setting has to be provided in *<<config-format-duration, duration format>>*.
246-
If a request to the APM server takes longer than the configured timeout,
246+
If a request to the APM Server takes longer than the configured timeout,
247247
the request is cancelled and the event (exception or transaction) is discarded.
248248
Set to `None` to disable timeouts.
249249

250250
WARNING: If timeouts are disabled or set to a high value,
251-
your app could experience memory issues if the APM server times out.
251+
your app could experience memory issues if the APM Server times out.
252252

253253

254254
[float]
@@ -261,7 +261,7 @@ your app could experience memory issues if the APM server times out.
261261
| `ELASTIC_APM_HOSTNAME` | `HOSTNAME` | `socket.gethostname()` | `app-server01.example.com`
262262
|============
263263

264-
The host name to use when sending error and transaction data to the APM server.
264+
The host name to use when sending error and transaction data to the APM Server.
265265

266266
[float]
267267
[[config-auto-log-stacks]]
@@ -407,7 +407,7 @@ filter such data.
407407

408408
Limits the amount of spans that are recorded per transaction.
409409
This is helpful in cases where a transaction creates a very high amount of spans (e.g. thousands of SQL queries).
410-
Setting an upper limit will prevent overloading the agent and the APM server with too much work for such edge cases.
410+
Setting an upper limit will prevent overloading the agent and the APM Server with too much work for such edge cases.
411411

412412
[float]
413413
[[config-span-frames-min-duration]]
@@ -440,8 +440,8 @@ this setting has to be provided in *<<config-format-duration, duration format>>*
440440
| `ELASTIC_APM_API_REQUEST_SIZE` | `API_REQUEST_SIZE` | `"724kb"`
441441
|============
442442

443-
Maximum queue length of the request buffer before sending the request to the APM server.
444-
A lower value will increase the load on your APM server,
443+
Maximum queue length of the request buffer before sending the request to the APM Server.
444+
A lower value will increase the load on your APM Server,
445445
while a higher value can increase the memory pressure of your app.
446446
A higher value also impacts the time until data is indexed and searchable in Elasticsearch.
447447

@@ -460,8 +460,8 @@ By default, the APM Server limits request payload size to 1 MByte.
460460
| `ELASTIC_APM_API_REQUEST_TIME` | `API_REQUEST_TIME` | `"10s"`
461461
|============
462462

463-
Maximum queue time of the request buffer before sending the request to the APM server.
464-
A lower value will increase the load on your APM server,
463+
Maximum queue time of the request buffer before sending the request to the APM Server.
464+
A lower value will increase the load on your APM Server,
465465
while a higher value can increase the memory pressure of your app.
466466
A higher value also impacts the time until data is indexed and searchable in Elasticsearch.
467467

@@ -552,7 +552,7 @@ The default value varies based on your Python version and implementation, e.g.:
552552
|============
553553

554554
If your app is in debug mode (e.g. in Django with `settings.DEBUG = True` or in Flask with `app.debug = True`),
555-
the agent won't send any data to the APM server. You can override it by changing this setting to `True`.
555+
the agent won't send any data to the APM Server. You can override it by changing this setting to `True`.
556556

557557

558558
[float]
@@ -563,7 +563,7 @@ the agent won't send any data to the APM server. You can override it by changing
563563
| `ELASTIC_APM_DISABLE_SEND` | `DISABLE_SEND` | `False`
564564
|============
565565

566-
If set to `True`, the agent won't send any events to the APM server, independent of any debug state.
566+
If set to `True`, the agent won't send any events to the APM Server, independent of any debug state.
567567

568568

569569
[float]
@@ -586,7 +586,7 @@ This disables most of the tracing functionality, but can be useful to debug poss
586586
| `ELASTIC_APM_VERIFY_SERVER_CERT` | `VERIFY_SERVER_CERT` | `True`
587587
|============
588588

589-
By default, the agent verifies the SSL certificate if you use an HTTPS connection to the APM server.
589+
By default, the agent verifies the SSL certificate if you use an HTTPS connection to the APM Server.
590590
Verification can be disabled by changing this setting to `False`.
591591
This setting is ignored when <<config-server-cert,`server_cert`>> is set.
592592

@@ -698,6 +698,32 @@ If you want to use the route instead of the view name as the transaction name, y
698698

699699
NOTE: in versions previous to Django 2.2, changing this setting will have no effect.
700700

701+
[float]
702+
[[config-generic-environment]]
703+
=== Generic Environment variables
704+
705+
Some environment variables that are not specific to the APM agent can be used to configure the agent.
706+
707+
[float]
708+
[[config-generic-http-proxy]]
709+
==== `HTTP_PROXY` and `HTTPS_PROXY`
710+
711+
Using `HTTP_PROXY` and `HTTPS_PROXY`, the agent can be instructed to use a proxy to connect to the APM Server.
712+
If both are set, `HTTPS_PROXY` takes precedence.
713+
714+
NOTE: The environment variables are case-insensitive.
715+
716+
[float]
717+
[[config-generic-no-proxy]]
718+
==== `NO_PROXY`
719+
720+
To instruct the agent to *not* use a proxy, you can use the `NO_PROXY` environment variable.
721+
You can either set it to a comma-separated list of hosts for which no proxy should be used (e.g. `localhost,example.com`)
722+
or use `*` to match any host.
723+
724+
This is useful if `HTTP_PROXY` / `HTTPS_PROXY` is set for other reasons than agent / APM Server communication.
725+
726+
701727
[float]
702728
[[config-formats]]
703729
=== Configuration formats

docs/flask.asciidoc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ apm = ElasticAPM(app, service_name='<APP-ID>', secret_token='<SECRET-TOKEN>')
7171
[[flask-debug-mode]]
7272
==== Debug Mode
7373

74-
Please note that errors and transactions will only be sent to the apm server if your app is *not* in
74+
Please note that errors and transactions will only be sent to the APM Server if your app is *not* in
7575
http://flask.pocoo.org/docs/0.12/quickstart/#debug-mode[debug mode].
7676

7777
To force the agent to send data while the app is in debug mode,
@@ -192,7 +192,7 @@ def bar():
192192
app.logger.error( 'I cannot math', exc_info=True)
193193
----
194194

195-
NOTE: `exc_info=True` adds the exception info to the data that gets sent to the APM server.
195+
NOTE: `exc_info=True` adds the exception info to the data that gets sent to the APM Server.
196196
Without it, only the message is sent.
197197

198198
[float]
@@ -221,7 +221,7 @@ def bar():
221221
[[flask-celery-tasks]]
222222
==== Celery tasks
223223

224-
The Elastic APM agent will automatically send errors and performance data from your Celery tasks to the APM server.
224+
The Elastic APM agent will automatically send errors and performance data from your Celery tasks to the APM Server.
225225

226226
[float]
227227
[[flask-performance-metrics]]

elasticapm/transport/http.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232

3333
import hashlib
3434
import logging
35-
import os
3635
import re
3736
import ssl
3837

@@ -50,6 +49,7 @@
5049
class Transport(HTTPTransportBase):
5150
def __init__(self, url, **kwargs):
5251
super(Transport, self).__init__(url, **kwargs)
52+
url_parts = compat.urlparse.urlparse(url)
5353
pool_kwargs = {"cert_reqs": "CERT_REQUIRED", "ca_certs": certifi.where(), "block": True}
5454
if self._server_cert:
5555
pool_kwargs.update(
@@ -59,8 +59,9 @@ def __init__(self, url, **kwargs):
5959
elif not self._verify_server_cert:
6060
pool_kwargs["cert_reqs"] = ssl.CERT_NONE
6161
pool_kwargs["assert_hostname"] = False
62-
proxy_url = os.environ.get("HTTPS_PROXY", os.environ.get("HTTP_PROXY"))
63-
if proxy_url:
62+
proxies = compat.getproxies_environment()
63+
proxy_url = proxies.get("https", proxies.get("http", None))
64+
if proxy_url and not compat.proxy_bypass_environment(url_parts.netloc):
6465
self.http = urllib3.ProxyManager(proxy_url, **pool_kwargs)
6566
else:
6667
self.http = urllib3.PoolManager(**pool_kwargs)

elasticapm/utils/compat.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ def uwsgi_atexit():
8181
import Queue as queue # noqa F401
8282
import urlparse # noqa F401
8383
from urllib2 import HTTPError # noqa F401
84+
from urllib import proxy_bypass_environment, getproxies_environment # noqa F401
8485

8586
StringIO = BytesIO = StringIO.StringIO
8687

@@ -112,6 +113,7 @@ def iterlists(d, **kw):
112113
import queue # noqa F401
113114
from urllib import parse as urlparse # noqa F401
114115
from urllib.error import HTTPError # noqa F401
116+
from urllib.request import proxy_bypass_environment, getproxies_environment # noqa F401
115117

116118
StringIO = io.StringIO
117119
BytesIO = io.BytesIO

tests/transports/test_urllib3.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def test_https_proxy_environment_variable():
116116

117117

118118
def test_https_proxy_environment_variable_is_preferred():
119-
with mock.patch.dict("os.environ", {"HTTPS_PROXY": "https://example.com", "HTTP_PROXY": "http://example.com"}):
119+
with mock.patch.dict("os.environ", {"https_proxy": "https://example.com", "HTTP_PROXY": "http://example.com"}):
120120
transport = Transport("http://localhost:9999")
121121
try:
122122
assert isinstance(transport.http, urllib3.poolmanager.ProxyManager)
@@ -125,6 +125,24 @@ def test_https_proxy_environment_variable_is_preferred():
125125
transport.close()
126126

127127

128+
def test_no_proxy_star():
129+
with mock.patch.dict("os.environ", {"HTTPS_PROXY": "https://example.com", "NO_PROXY": "*"}):
130+
transport = Transport("http://localhost:9999")
131+
try:
132+
assert not isinstance(transport.http, urllib3.poolmanager.ProxyManager)
133+
finally:
134+
transport.close()
135+
136+
137+
def test_no_proxy_host():
138+
with mock.patch.dict("os.environ", {"HTTPS_PROXY": "https://example.com", "NO_PROXY": "localhost"}):
139+
transport = Transport("http://localhost:9999")
140+
try:
141+
assert not isinstance(transport.http, urllib3.poolmanager.ProxyManager)
142+
finally:
143+
transport.close()
144+
145+
128146
def test_header_encodings():
129147
"""
130148
Tests that headers are encoded as bytestrings. If they aren't,

0 commit comments

Comments
 (0)