Skip to content

Commit 8fc379d

Browse files
LaunchDarklyReleaseBotapache-hbeli-darklyLaunchDarklyCIbwoskow-ld
authored
prepare 8.1.4 release (#211)
## [8.1.4] - 2023-05-31 ### Fixed: - Password will be redacted from redis URL prior to logging. --------- Co-authored-by: Elliot <[email protected]> Co-authored-by: Eli Bishop <[email protected]> Co-authored-by: LaunchDarklyCI <[email protected]> Co-authored-by: Ben Woskow <[email protected]> Co-authored-by: LaunchDarklyCI <[email protected]> Co-authored-by: hroederld <[email protected]> Co-authored-by: Robert J. Neal <[email protected]> Co-authored-by: Robert J. Neal <[email protected]> Co-authored-by: Ember Stevens <[email protected]> Co-authored-by: ember-stevens <[email protected]> Co-authored-by: Matthew M. Keeler <[email protected]> Co-authored-by: charukiewicz <[email protected]> Co-authored-by: LaunchDarklyReleaseBot <[email protected]> Co-authored-by: Christian Charukiewicz <[email protected]> Co-authored-by: Matthew M. Keeler <[email protected]> Co-authored-by: Ben Woskow <[email protected]> Co-authored-by: Gavin Whelan <[email protected]> Co-authored-by: Gabor Angeli <[email protected]> Co-authored-by: Elliot <[email protected]> Co-authored-by: Louis Chan <[email protected]> Co-authored-by: prpnmac <[email protected]>
1 parent a2b221e commit 8fc379d

File tree

5 files changed

+40
-4
lines changed

5 files changed

+40
-4
lines changed

ldclient/impl/integrations/redis/redis_big_segment_store.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from ldclient import log
22
from ldclient.interfaces import BigSegmentStore, BigSegmentStoreMetadata
3+
from ldclient.impl.util import redact_password
34

45
from typing import Any, Optional, Dict, Set, cast
56

@@ -21,7 +22,7 @@ def __init__(self, url: str, prefix: Optional[str], redis_opts: Dict[str, Any]):
2122
raise NotImplementedError("Cannot use Redis Big Segment store because redis package is not installed")
2223
self._prefix = prefix or 'launchdarkly'
2324
self._pool = redis.ConnectionPool.from_url(url=url, **redis_opts)
24-
log.info("Started RedisBigSegmentStore connected to URL: " + url + " using prefix: " + self._prefix)
25+
log.info("Started RedisBigSegmentStore connected to URL: " + redact_password(url) + " using prefix: " + self._prefix)
2526

2627
def get_metadata(self) -> BigSegmentStoreMetadata:
2728
r = redis.Redis(connection_pool=self._pool)

ldclient/impl/integrations/redis/redis_feature_store.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from ldclient import log
1111
from ldclient.interfaces import DiagnosticDescription, FeatureStoreCore
1212
from ldclient.versioned_data_kind import FEATURES
13+
from ldclient.impl.util import redact_password
1314

1415
from typing import Any, Dict
1516

@@ -21,7 +22,7 @@ def __init__(self, url, prefix, redis_opts: Dict[str, Any]):
2122
self._prefix = prefix or 'launchdarkly'
2223
self._pool = redis.ConnectionPool.from_url(url=url, **redis_opts)
2324
self.test_update_hook = None # exposed for testing
24-
log.info("Started RedisFeatureStore connected to URL: " + url + " using prefix: " + self._prefix)
25+
log.info("Started RedisFeatureStore connected to URL: " + redact_password(url) + " using prefix: " + self._prefix)
2526

2627
def _items_key(self, kind):
2728
return "{0}:{1}".format(self._prefix, kind.namespace)

ldclient/impl/util.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from typing import Any
77
from ldclient.impl.http import _base_headers
8+
from urllib.parse import urlparse, urlunparse
89

910

1011
def current_time_millis() -> int:
@@ -132,3 +133,17 @@ def stringify_attrs(attrdict, attrs):
132133
newdict = attrdict.copy()
133134
newdict[attr] = str(val)
134135
return attrdict if newdict is None else newdict
136+
137+
def redact_password(url: str) -> str:
138+
"""
139+
Replace any embedded password in the provided URL with 'xxxx'. This is
140+
useful for ensuring sensitive information included in a URL isn't logged.
141+
"""
142+
parts = urlparse(url)
143+
if parts.password is None:
144+
return url
145+
146+
updated = parts.netloc.replace(parts.password, "xxxx")
147+
parts = parts._replace(netloc=updated)
148+
149+
return urlunparse(parts)

testing/test_config.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ def application_will_ignore_invalid_keys():
6363
":",
6464
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._-a"
6565
])
66-
def application_will_drop_invalid_values(value):
67-
application = {"id": value, "version": value}
66+
def invalid_application_tags(request):
67+
return request.param
68+
69+
def test_application_will_drop_invalid_values(invalid_application_tags):
70+
application = {"id": invalid_application_tags, "version": invalid_application_tags}
6871
config = Config(sdk_key = "SDK_KEY", application = application)
6972
assert config.application == {"id": "", "version": ""}

testing/test_util.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from ldclient.impl.util import redact_password
2+
import pytest
3+
4+
@pytest.fixture(params = [
5+
("rediss://user:password=@redis-server-url:6380/0?ssl_cert_reqs=CERT_REQUIRED", "rediss://user:xxxx@redis-server-url:6380/0?ssl_cert_reqs=CERT_REQUIRED"),
6+
("rediss://user-matches-password:user-matches-password@redis-server-url:6380/0?ssl_cert_reqs=CERT_REQUIRED", "rediss://xxxx:xxxx@redis-server-url:6380/0?ssl_cert_reqs=CERT_REQUIRED"),
7+
("rediss://redis-server-url", "rediss://redis-server-url"),
8+
("invalid urls are left alone", "invalid urls are left alone"),
9+
])
10+
def password_redaction_tests(request):
11+
return request.param
12+
13+
def test_can_redact_password(password_redaction_tests):
14+
input, expected = password_redaction_tests
15+
16+
assert redact_password(input) == expected

0 commit comments

Comments
 (0)