Skip to content

Commit 70f0ce0

Browse files
edwarj2justineyster
authored andcommitted
Cloudant 2 (Yelp#207)
* clarify var names in test * help text * correcting account / pw test verification path * correcting validation error response * change detector vars & add cases * detection tests clean pending verification tests * all tests clean * added more key assignment tests * PR simplifications * fix capture group * fix capture group 2
1 parent 7aad9f3 commit 70f0ce0

File tree

2 files changed

+70
-39
lines changed

2 files changed

+70
-39
lines changed

Diff for: detect_secrets/plugins/cloudant.py

+28-17
Original file line numberDiff line numberDiff line change
@@ -17,37 +17,48 @@ class CloudantDetector(RegexBasedDetector):
1717
opt_dashes = r'(?:--|)'
1818
opt_dot = r'(?:\.|)'
1919
dot = r'\.'
20-
cl_account = r'[0-9a-z\-\_]*'
21-
cl = r'(cloudant|cl|clou)'
20+
cl_account = r'[0-9a-z\-\_]+'
21+
cl = r'(?:cloudant|cl|clou)'
2222
opt_dash_undrscr = r'(?:_|-|)'
2323
opt_api = r'(?:api|)'
24-
cl_key_or_pass = cl + opt_dash_undrscr + r'(?:key|pwd|pw|password|pass|token)'
24+
cl_key_or_pass = opt_api + r'(?:key|pwd|pw|password|pass|token)'
2525
opt_space = r'(?: |)'
2626
assignment = r'(?:=|:|:=|=>)'
27-
cl_secret = r'[0-9a-f]{64}'
27+
cl_pw = r'([0-9a-f]{64})'
28+
cl_api_key = r'([a-z]{24})'
2829
colon = r'\:'
2930
at = r'\@'
30-
http = r'(?:http\:\/\/|https\:\/\/)'
31+
http = r'(?:https?\:\/\/)'
3132
cloudant_api_url = r'cloudant\.com'
3233
denylist = [
34+
RegexBasedDetector.assign_regex_generator(
35+
prefix_regex=cl,
36+
password_keyword_regex=cl_key_or_pass,
37+
password_regex=cl_pw,
38+
),
39+
RegexBasedDetector.assign_regex_generator(
40+
prefix_regex=cl,
41+
password_keyword_regex=cl_key_or_pass,
42+
password_regex=cl_api_key,
43+
),
3344
re.compile(
34-
r'{cl_key_or_pass}{opt_space}{assignment}{opt_space}{opt_quote}{cl_secret}'.format(
35-
cl_key_or_pass=cl_key_or_pass,
36-
opt_quote=opt_quote,
45+
r'{http}{cl_account}{colon}{cl_pw}{at}{cl_account}{dot}{cloudant_api_url}'.format(
46+
http=http,
47+
colon=colon,
3748
cl_account=cl_account,
38-
opt_dash_undrscr=opt_dash_undrscr,
39-
opt_api=opt_api,
40-
opt_space=opt_space,
41-
assignment=assignment,
42-
cl_secret=cl_secret,
43-
), flags=re.IGNORECASE,
49+
cl_pw=cl_pw,
50+
at=at,
51+
dot=dot,
52+
cloudant_api_url=cloudant_api_url,
53+
),
54+
flags=re.IGNORECASE,
4455
),
4556
re.compile(
46-
r'{http}{cl_account}{colon}{cl_secret}{at}{cl_account}{dot}{cloudant_api_url}'.format(
57+
r'{http}{cl_account}{colon}{cl_api_key}{at}{cl_account}{dot}{cloudant_api_url}'.format(
4758
http=http,
4859
colon=colon,
4960
cl_account=cl_account,
50-
cl_secret=cl_secret,
61+
cl_api_key=cl_api_key,
5162
at=at,
5263
dot=dot,
5364
cloudant_api_url=cloudant_api_url,
@@ -105,7 +116,7 @@ def verify_cloudant_key(hostname, token, potential_secret=None):
105116
request_url = 'https://{hostname}:' \
106117
'{token}' \
107118
'@{hostname}.' \
108-
'cloudant.com/_api/v2'.format(
119+
'cloudant.com'.format(
109120
hostname=hostname,
110121
token=token,
111122
)

Diff for: tests/plugins/cloudant_test.py

+42-22
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@
1111
from detect_secrets.plugins.cloudant import get_host
1212

1313
CL_HOST = 'testy_test' # also called user
14-
# only detecting 64 hex
15-
CL_TOKEN = 'abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234'
14+
# only detecting 64 hex CL generated password
15+
CL_PW = 'abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234'
16+
17+
# detecting 24 alpha for CL generated API KEYS
18+
CL_API_KEY = 'abcdefghijabcdefghijabcd'
1619

1720

1821
class TestCloudantDetector(object):
@@ -21,25 +24,42 @@ class TestCloudantDetector(object):
2124
'payload, should_flag',
2225
[
2326
(
24-
'https://{cl_host}:{cl_token}@{cl_host}.cloudant.com"'.format(
25-
cl_host=CL_HOST, cl_token=CL_TOKEN,
27+
'https://{cl_host}:{cl_pw}@{cl_host}.cloudant.com"'.format(
28+
cl_host=CL_HOST, cl_pw=CL_PW,
29+
), True,
30+
),
31+
(
32+
'https://{cl_host}:{cl_pw}@{cl_host}.cloudant.com/_api/v2/'.format(
33+
cl_host=CL_HOST, cl_pw=CL_PW,
34+
), True,
35+
),
36+
(
37+
'https://{cl_host}:{cl_pw}@{cl_host}.cloudant.com/_api/v2/'.format(
38+
cl_host=CL_HOST, cl_pw=CL_PW,
39+
), True,
40+
),
41+
(
42+
'https://{cl_host}:{cl_pw}@{cl_host}.cloudant.com'.format(
43+
cl_host=CL_HOST, cl_pw=CL_PW,
2644
), True,
2745
),
2846
(
29-
'https://{cl_host}:{cl_token}@{cl_host}.cloudant.com/_api/v2/'.format(
30-
cl_host=CL_HOST, cl_token=CL_TOKEN,
47+
'https://{cl_host}:{cl_api_key}@{cl_host}.cloudant.com'.format(
48+
cl_host=CL_HOST, cl_api_key=CL_API_KEY,
3149
), True,
3250
),
3351
(
34-
'https://{cl_host}:{cl_token}.cloudant.com'.format(
35-
cl_host=CL_HOST, cl_token=CL_TOKEN,
52+
'https://{cl_host}:{cl_pw}.cloudant.com'.format(
53+
cl_host=CL_HOST, cl_pw=CL_PW,
3654
), False,
3755
),
38-
('cloudant_password=\'{cl_token}\''.format(cl_token=CL_TOKEN), True),
39-
('cloudant_pw=\'{cl_token}\''.format(cl_token=CL_TOKEN), True),
40-
('cloudant_pw="{cl_token}"'.format(cl_token=CL_TOKEN), True),
41-
('clou_pw = "{cl_token}"'.format(cl_token=CL_TOKEN), True),
56+
('cloudant_password=\'{cl_pw}\''.format(cl_pw=CL_PW), True),
57+
('cloudant_pw=\'{cl_pw}\''.format(cl_pw=CL_PW), True),
58+
('cloudant_pw="{cl_pw}"'.format(cl_pw=CL_PW), True),
59+
('clou_pw = "{cl_pw}"'.format(cl_pw=CL_PW), True),
60+
('cloudant_key = "{cl_api_key}"'.format(cl_api_key=CL_API_KEY), True),
4261
('cloudant_password = "a-fake-tooshort-key"', False),
62+
('cl_api_key = "a-fake-api-key"', False),
4363
],
4464
)
4565
def test_analyze_string(self, payload, should_flag):
@@ -50,31 +70,31 @@ def test_analyze_string(self, payload, should_flag):
5070

5171
@responses.activate
5272
def test_verify_invalid_secret(self):
53-
cl_api_url = 'https://{cl_host}:{cl_token}@{cl_host}.cloudant.com/_api/v2'.format(
54-
cl_host=CL_HOST, cl_token=CL_TOKEN,
73+
cl_api_url = 'https://{cl_host}:{cl_pw}@{cl_host}.cloudant.com'.format(
74+
cl_host=CL_HOST, cl_pw=CL_PW,
5575
)
5676
responses.add(
5777
responses.GET, cl_api_url,
58-
json={'error': 'Access denied. '}, status=401,
78+
json={'error': 'unauthorized'}, status=401,
5979
)
6080

6181
assert CloudantDetector().verify(
62-
CL_TOKEN,
82+
CL_PW,
6383
'cloudant_host={}'.format(CL_HOST),
6484
) == VerifiedResult.VERIFIED_FALSE
6585

6686
@responses.activate
6787
def test_verify_valid_secret(self):
68-
cl_api_url = 'https://{cl_host}:{cl_token}@{cl_host}.cloudant.com/_api/v2'.format(
69-
cl_host=CL_HOST, cl_token=CL_TOKEN,
88+
cl_api_url = 'https://{cl_host}:{cl_pw}@{cl_host}.cloudant.com'.format(
89+
cl_host=CL_HOST, cl_pw=CL_PW,
7090
)
7191
responses.add(
7292
responses.GET, cl_api_url,
7393
json={'id': 1}, status=200,
7494
)
75-
potential_secret = PotentialSecret('test cloudant', 'test filename', CL_TOKEN)
95+
potential_secret = PotentialSecret('test cloudant', 'test filename', CL_PW)
7696
assert CloudantDetector().verify(
77-
CL_TOKEN,
97+
CL_PW,
7898
'cloudant_host={}'.format(CL_HOST),
7999
potential_secret,
80100
) == VerifiedResult.VERIFIED_TRUE
@@ -83,13 +103,13 @@ def test_verify_valid_secret(self):
83103
@responses.activate
84104
def test_verify_unverified_secret(self):
85105
assert CloudantDetector().verify(
86-
CL_TOKEN,
106+
CL_PW,
87107
'cloudant_host={}'.format(CL_HOST),
88108
) == VerifiedResult.UNVERIFIED
89109

90110
def test_verify_no_secret(self):
91111
assert CloudantDetector().verify(
92-
CL_TOKEN,
112+
CL_PW,
93113
'no_un={}'.format(CL_HOST),
94114
) == VerifiedResult.UNVERIFIED
95115

0 commit comments

Comments
 (0)