Skip to content

Commit 955c2f8

Browse files
author
Glenn Snyder
committed
adding support for v3.7.x REST API authentication
1 parent 9e0a8ea commit 955c2f8

File tree

3 files changed

+130
-6
lines changed

3 files changed

+130
-6
lines changed

blackduck/HubRestApi.py

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ class CreateFailedAlreadyExists(Exception):
5656
class CreateFailedUnknown(Exception):
5757
pass
5858

59+
class UnknownVersion(Exception):
60+
pass
61+
5962
class HubInstance(object):
6063
'''
6164
classdocs
@@ -89,7 +92,8 @@ def __init__(self, *args, **kwargs):
8992
if self.config['debug']:
9093
print(self.configfile)
9194

92-
self.token, self.csrf_token = self.get_auth_token()
95+
self.token, self.csrf_token, self.cookie = self.get_auth_token()
96+
self.bd_major_version = self._get_major_version()
9397

9498

9599
def read_config(self):
@@ -114,7 +118,7 @@ def get_auth_token(self):
114118
)
115119
csrf_token = response.headers['X-CSRF-TOKEN']
116120
bearer_token = json.loads(response.content.decode('utf-8'))['bearerToken']
117-
return (bearer_token, csrf_token)
121+
return (bearer_token, csrf_token, None)
118122
else:
119123
authendpoint="/j_spring_security_check"
120124
url = self.config['baseurl'] + authendpoint
@@ -125,8 +129,27 @@ def get_auth_token(self):
125129
response = session.post(url, credentials, verify= not self.config['insecure'])
126130
cookie = response.headers['Set-Cookie']
127131
token = cookie[cookie.index('=')+1:cookie.index(';')]
128-
return (token, None)
132+
return (token, None, cookie)
129133

134+
def _get_major_version(self):
135+
'''Get the version info from the server, if available, and
136+
return the major version number as string
137+
'''
138+
session = requests.session()
139+
url = self.config['baseurl'] + "/api/current-version"
140+
response = session.get(url, verify = not self.config['insecure'])
141+
version_info = response.json()
142+
143+
if response.status_code == 200:
144+
if 'version' in version_info:
145+
return version_info['version'].split(".")[0]
146+
else:
147+
raise UnknownVersion("Did not find the 'version' key in the response to a successful GET on /api/current-version")
148+
else:
149+
# the only version of Black Duck not having the /api/current-version
150+
# endpoint are v3, so assume it's that
151+
return "3"
152+
130153
def get_urlbase(self):
131154
return self.config['baseurl']
132155

@@ -137,7 +160,10 @@ def get_headers(self):
137160
'Authorization': 'Bearer {}'.format(self.token),
138161
'Content-Type': 'application/json'}
139162
else:
140-
return {"Authorization":"Bearer " + self.token}
163+
if self.bd_major_version == "3":
164+
return {"Cookie": self.cookie}
165+
else:
166+
return {"Authorization":"Bearer " + self.token}
141167

142168
def get_api_version(self):
143169
url = self.get_urlbase() + '/api/current-version'

blackduck/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11

2-
VERSION = (0, 0, 4)
2+
VERSION = (0, 0, 5)
33

44
__version__ = '.'.join(map(str, VERSION))

test/test_hub_rest_api_python.py

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,21 @@ def teardown_function(function):
4343
@pytest.fixture()
4444
def mock_hub_instance(requests_mock):
4545
requests_mock.post(
46-
"https://my-hub-host/j_spring_security_check",
46+
"{}/j_spring_security_check".format(fake_hub_host),
4747
headers={"Set-Cookie": 'AUTHORIZATION_BEARER={}; Path=/; secure; Secure; HttpOnly'.format(invalid_bearer_token)}
4848
)
49+
requests_mock.get(
50+
"{}/api/current-version".format(fake_hub_host),
51+
json = {
52+
"version": "2018.11.0",
53+
"_meta": {
54+
"allow": [
55+
"GET"
56+
],
57+
"href": "{}/api/current-version".format(fake_hub_host)
58+
}
59+
}
60+
)
4961
yield HubInstance(fake_hub_host, "a_username", "a_password")
5062

5163
@pytest.fixture()
@@ -58,6 +70,18 @@ def mock_hub_instance_using_api_token(requests_mock):
5870
'Content-Type': 'application/json'
5971
}
6072
)
73+
requests_mock.get(
74+
"{}/api/current-version".format(fake_hub_host),
75+
json = {
76+
"version": "2018.11.0",
77+
"_meta": {
78+
"allow": [
79+
"GET"
80+
],
81+
"href": "{}/api/current-version".format(fake_hub_host)
82+
}
83+
}
84+
)
6185

6286
yield HubInstance(fake_hub_host, api_token=made_up_api_token)
6387

@@ -82,6 +106,54 @@ def test_vulnerability_info(requests_mock):
82106
with open("sample-vulnerability.json") as sample_vulnerability_file:
83107
yield json.loads(sample_vulnerability_file.read())
84108

109+
def test_get_major_version(requests_mock):
110+
requests_mock.post(
111+
"{}/j_spring_security_check".format(fake_hub_host),
112+
headers={"Set-Cookie": 'AUTHORIZATION_BEARER={}; Path=/; secure; Secure; HttpOnly'.format(invalid_bearer_token)}
113+
)
114+
for version in ["2018.11.0", "5.0.2", "4.8.3", "3.7.2"]:
115+
expected = version.split(".")[0]
116+
requests_mock.get(
117+
"{}/api/current-version".format(fake_hub_host),
118+
json = {
119+
"version": "{}".format(version),
120+
"_meta": {
121+
"allow": [
122+
"GET"
123+
],
124+
"href": "{}/api/current-version".format(fake_hub_host)
125+
}
126+
}
127+
)
128+
hub = HubInstance(fake_hub_host, "a_username", "a_password")
129+
assert hub.bd_major_version == expected
130+
131+
def test_get_headers(mock_hub_instance):
132+
# somewhat contrived, but it does execute all the paths
133+
# TODO: better way to test this one?
134+
#
135+
the_api_token = "fake-api-token"
136+
the_csrf_token = "fake-csrf-token"
137+
the_token = "fake-bearer-token"
138+
mock_hub_instance.config['api_token'] = the_api_token
139+
mock_hub_instance.csrf_token = the_csrf_token
140+
mock_hub_instance.token = the_token
141+
142+
assert mock_hub_instance.get_headers() == {
143+
'X-CSRF-TOKEN': the_csrf_token,
144+
'Authorization': "Bearer {}".format(the_token),
145+
'Content-Type': 'application/json'}
146+
147+
del mock_hub_instance.config['api_token']
148+
for bd_major_version in ["2018", "5", "4", "3"]:
149+
if bd_major_version == "3":
150+
expected = {"Cookie": mock_hub_instance.cookie}
151+
else:
152+
expected = {"Authorization":"Bearer " + mock_hub_instance.token}
153+
154+
mock_hub_instance.bd_major_version = bd_major_version
155+
assert mock_hub_instance.get_headers() == expected
156+
85157
def test_get_policy_url(mock_hub_instance):
86158
assert mock_hub_instance._get_policy_url() == fake_hub_host + "/api/policy-rules"
87159

@@ -114,6 +186,19 @@ def test_hub_instance_with_write_config(requests_mock):
114186
"https://my-hub-host/j_spring_security_check",
115187
headers={"Set-Cookie": 'AUTHORIZATION_BEARER={}; Path=/; secure; Secure; HttpOnly'.format(invalid_bearer_token)}
116188
)
189+
requests_mock.get(
190+
"{}/api/current-version".format(fake_hub_host),
191+
json = {
192+
"version": "2018.11.0",
193+
"_meta": {
194+
"allow": [
195+
"GET"
196+
],
197+
"href": "{}/api/current-version".format(fake_hub_host)
198+
}
199+
}
200+
)
201+
117202
with patch("builtins.open", new_callable=mock_open()) as m:
118203
with patch('json.dump') as m_json:
119204
hub = HubInstance(fake_hub_host, "a_username", "a_password")
@@ -126,6 +211,19 @@ def test_hub_instance_with_write_config_false(requests_mock):
126211
"https://my-hub-host/j_spring_security_check",
127212
headers={"Set-Cookie": 'AUTHORIZATION_BEARER={}; Path=/; secure; Secure; HttpOnly'.format(invalid_bearer_token)}
128213
)
214+
requests_mock.get(
215+
"{}/api/current-version".format(fake_hub_host),
216+
json = {
217+
"version": "2018.11.0",
218+
"_meta": {
219+
"allow": [
220+
"GET"
221+
],
222+
"href": "{}/api/current-version".format(fake_hub_host)
223+
}
224+
}
225+
)
226+
129227
with patch.object(HubInstance, "write_config") as mock_write_config:
130228
hub = HubInstance(fake_hub_host, "a_username", "a_password", write_config_flag=False)
131229

0 commit comments

Comments
 (0)