Skip to content

Commit 05e245d

Browse files
author
Glenn Snyder
committed
adding utilities to dump, upload users, user groups, policies
1 parent 6fea8f6 commit 05e245d

File tree

8 files changed

+664
-6
lines changed

8 files changed

+664
-6
lines changed

blackduck/HubRestApi.py

Lines changed: 148 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,141 @@ def _get_parameter_string(self, parameters={}):
175175
parameter_string = "&".join(["{}={}".format(k,v) for k,v in parameters.items()])
176176
return "?" + parameter_string
177177

178+
###
179+
#
180+
# Role stuff
181+
#
182+
###
183+
def _get_role_url(self):
184+
return self.config['baseurl'] + "/api/roles"
185+
186+
def get_roles(self, parameters={}):
187+
url = self._get_role_url() + self._get_parameter_string(parameters)
188+
response = self.execute_get(url)
189+
return response.json()
190+
191+
def get_roles_url_from_user_or_group(self, user_or_group):
192+
roles_url = None
193+
for endpoint in user_or_group['_meta']['links']:
194+
if endpoint['rel'] == "roles":
195+
roles_url = endpoint['href']
196+
return roles_url
197+
198+
def get_roles_for_user_or_group(self, user_or_group):
199+
roles_url = self.get_roles_url_from_user_or_group(user_or_group)
200+
if roles_url:
201+
return self.execute_get(roles_url)
202+
else:
203+
return None
204+
205+
def get_role_url_by_name(self, role_name):
206+
# Return the role URL for this server corresponding to the role name
207+
all_roles = self.get_roles()
208+
for role in all_roles['items']:
209+
if role['name'] == role_name:
210+
return role['_meta']['href']
211+
return None
212+
213+
def assign_role_to_user_or_group(self, role_name, user_or_group):
214+
user_or_group_roles_url = self.get_roles_url_from_user_or_group(user_or_group)
215+
return self.assign_role_given_role_url(role_name, user_or_group_roles_url)
216+
217+
def assign_role_given_role_url(self, role_name, user_or_group_role_assignment_url):
218+
role_url = self.get_role_url_by_name(role_name)
219+
if self.bd_major_version == "3":
220+
# A hack to get the assignment to work on v3
221+
role_url = role_url.replace("api", "api/internal")
222+
data = {"name": role_name, "role": role_url}
223+
logging.debug("executing POST to {} with {}".format(
224+
user_or_group_role_assignment_url, data))
225+
return self.execute_post(user_or_group_role_assignment_url, data = data)
226+
227+
228+
###
229+
#
230+
# User stuff
231+
#
232+
###
233+
def _get_user_url(self):
234+
return self.config['baseurl'] + "/api/users"
235+
236+
def get_users(self, parameters={}):
237+
url = self._get_user_url() + self._get_parameter_string(parameters)
238+
response = self.execute_get(url)
239+
return response.json()
240+
241+
def create_user(self, user_json):
242+
url = self._get_user_url()
243+
location = self._create(url, user_json)
244+
return location
245+
246+
def get_user_by_id(self, user_id):
247+
url = self._get_user_url() + "/{}".format(user_id)
248+
return self.get_user_by_url(url)
249+
250+
def get_user_by_url(self, user_url):
251+
response = self.execute_get(user_url)
252+
jsondata = response.json()
253+
return jsondata
254+
255+
def update_user_by_id(self, user_id, update_json):
256+
url = self._get_user_url() + "/{}".format(user_id)
257+
return self.update_user_by_url(url, update_json)
258+
259+
def update_user_by_url(self, user_url, update_json):
260+
return self.execute_put(user_url, update_json)
261+
262+
def delete_user_by_id(self, user_id):
263+
url = self._get_user_url() + "/{}".format(user_id)
264+
return self.delete_user_by_url(url)
265+
266+
def delete_user_by_url(self, user_url):
267+
return self.execute_delete(user_url)
268+
269+
###
270+
#
271+
# User group stuff
272+
#
273+
###
274+
def _get_user_group_url(self):
275+
return self.config['baseurl'] + "/api/usergroups"
276+
277+
def get_user_groups(self, parameters={}):
278+
url = self._get_user_group_url() + self._get_parameter_string(parameters)
279+
response = self.execute_get(url)
280+
return response.json()
281+
282+
def create_user_group(self, user_group_json):
283+
if self.bd_major_version == "3":
284+
url = self.config['baseurl'] + '/api/v1/usergroups'
285+
else:
286+
url = self._get_user_group_url()
287+
location = self._create(url, user_group_json)
288+
return location
289+
290+
def get_user_group_by_id(self, user_group_id):
291+
url = self._get_user_group_url() + "/{}".format(user_group_id)
292+
return self.get_user_group_by_url(url)
293+
294+
def get_user_group_by_url(self, user_group_url):
295+
response = self.execute_get(user_group_url)
296+
jsondata = response.json()
297+
return jsondata
298+
299+
def update_user_group_by_id(self, user_group_id, update_json):
300+
url = self._get_user_group_url() + "/{}".format(user_group_id)
301+
return self.update_user_group_by_url(url, update_json)
302+
303+
def update_user_group_by_url(self, user_group_url, update_json):
304+
return self.execute_put(user_group_url, update_json)
305+
306+
def delete_user_group_by_id(self, user_group_id):
307+
url = self._get_user_group_url() + "/{}".format(user_group_id)
308+
return self.delete_user_group_by_url(url)
309+
310+
def delete_user_group_by_url(self, user_group_url):
311+
return self.execute_delete(user_group_url)
312+
178313
###
179314
#
180315
# Policy stuff
@@ -527,8 +662,19 @@ def execute_put(self, url, data):
527662

528663
def _create(self, url, json_body):
529664
response = self.execute_post(url, json_body)
530-
if response.status_code == 201 and "location" in response.headers:
531-
return (response.headers["location"])
665+
response_json = response.json()
666+
# v4+ returns the newly created location in the response headers
667+
# and there is nothing in the response json
668+
# whereas v3 returns the newly created object in the response json
669+
if response.status_code == 201:
670+
if "location" in response.headers:
671+
return (response.headers["location"])
672+
elif '_meta' in response_json and 'href' in response_json['_meta']:
673+
return response_json['_meta']['href']
674+
else:
675+
# worst case, try returning the whole response json and let
676+
# client figure it out
677+
return response.json()
532678
elif response.status_code == 412:
533679
raise CreateFailedAlreadyExists("Failed to create the object because it already exists - url {}, body {}, response {}".format(url, json_body, response))
534680
else:

examples/dump_policies.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
'''
2+
Created on Dec 5, 2018
3+
4+
@author: gsnyder
5+
6+
Dump policies to a file
7+
8+
'''
9+
import argparse
10+
import json
11+
import logging
12+
from pprint import pprint
13+
import sys
14+
15+
from blackduck.HubRestApi import HubInstance, CreateFailedAlreadyExists
16+
17+
18+
def serialize_to_file(file, data):
19+
with open(file, "w") as f:
20+
json.dump(data, f, indent=3)
21+
22+
parser = argparse.ArgumentParser("Dump policies from a Hub instance")
23+
parser.add_argument("base_filename", help="There will be two files dumped - one raw and one prepped to copy policies to another Hub instance")
24+
args = parser.parse_args()
25+
26+
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
27+
28+
source_hub = HubInstance()
29+
30+
policy_keys_to_delete = [
31+
'_meta',
32+
'href',
33+
'links',
34+
'createdAt',
35+
'createdBy',
36+
'createdByUser',
37+
'updatedAt',
38+
'updatedBy',
39+
'updatedByUser']
40+
41+
policies_to_copy = source_hub.get_policies()
42+
43+
if 'totalCount' in policies_to_copy and policies_to_copy['totalCount'] > 0:
44+
logging.debug("Dumping {} policies from {}".format(policies_to_copy['totalCount'], source_hub.config['baseurl']))
45+
assert 'items' in policies_to_copy, "Should always be a list of items in a non-zero list of policies"
46+
47+
policy_data_raw = []
48+
policy_data_prepped_to_copy = []
49+
50+
for policy in policies_to_copy['items']:
51+
import pdb; pdb.set_trace()
52+
policy = source_hub.get_policy_by_url(policy['_meta']['href'])
53+
policy_data_raw.append(policy)
54+
55+
policy_copy_prepped_to_create = policy.copy()
56+
57+
for k in policy_keys_to_delete:
58+
if k in policy_copy_prepped_to_create:
59+
del policy_copy_prepped_to_create[k]
60+
61+
policy_data_prepped_to_copy.append(policy_copy_prepped_to_create)
62+
63+
raw_file = args.base_filename + ".raw"
64+
prepped_file = args.base_filename + ".prepped"
65+
66+
serialize_to_file(raw_file, policy_data_raw)
67+
serialize_to_file(prepped_file, policy_data_prepped_to_copy)
68+
else:
69+
logging.info("No policies to dump")
70+
71+
72+
73+

examples/dump_user_groups.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
'''
2+
Created on Dec 5, 2018
3+
4+
@author: gsnyder
5+
6+
Dump user groups to a file
7+
8+
'''
9+
import argparse
10+
import json
11+
import logging
12+
from pprint import pprint
13+
import sys
14+
15+
from blackduck.HubRestApi import HubInstance, CreateFailedAlreadyExists
16+
17+
18+
def serialize_to_file(file, data):
19+
with open(file, "w") as f:
20+
json.dump(data, f, indent=3)
21+
22+
parser = argparse.ArgumentParser("Dump user_groups from a Hub instance")
23+
parser.add_argument("base_filename", help="There will be two files dumped - one raw and one prepped to copy user_groups to another Hub instance")
24+
args = parser.parse_args()
25+
26+
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
27+
28+
source_hub = HubInstance()
29+
30+
user_group_keys_to_delete = ['_meta', 'href', 'links']
31+
32+
user_groups_to_copy = source_hub.get_user_groups()
33+
34+
if 'totalCount' in user_groups_to_copy and user_groups_to_copy['totalCount'] > 0:
35+
logging.debug("Dumping {} user_groups from {}".format(user_groups_to_copy['totalCount'], source_hub.config['baseurl']))
36+
assert 'items' in user_groups_to_copy, "Should always be a list of items in a non-zero list of user_groups"
37+
38+
user_group_data_raw = []
39+
user_group_data_prepped_to_copy = []
40+
41+
for user_group in user_groups_to_copy['items']:
42+
user_group_roles_response = source_hub.get_roles_for_user_or_group(user_group)
43+
if user_group_roles_response:
44+
user_group_roles = user_group_roles_response.json()
45+
else:
46+
user_group_roles = []
47+
48+
user_group_data_raw.append({
49+
'user_group': user_group, 'roles': user_group_roles
50+
})
51+
52+
user_group_copy_prepped_to_create = user_group.copy()
53+
for k in user_group_keys_to_delete:
54+
if k in user_group_copy_prepped_to_create:
55+
del user_group_copy_prepped_to_create[k]
56+
57+
user_group_roles_to_create = [role['name'] for role in user_group_roles['items']]
58+
59+
user_group_data_prepped_to_copy.append({
60+
'user_group': user_group_copy_prepped_to_create, 'roles': user_group_roles_to_create
61+
})
62+
63+
raw_file = args.base_filename + ".raw"
64+
prepped_file = args.base_filename + ".prepped"
65+
66+
serialize_to_file(raw_file, user_group_data_raw)
67+
serialize_to_file(prepped_file, user_group_data_prepped_to_copy)
68+
else:
69+
logging.info("No user groups to dump")
70+
71+
72+
73+

examples/dump_users.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
'''
2+
Created on Dec 4, 2018
3+
4+
@author: gsnyder
5+
6+
Copy users and their roles from one Hub instance to another
7+
8+
'''
9+
import argparse
10+
import json
11+
import logging
12+
from pprint import pprint
13+
import sys
14+
15+
from blackduck.HubRestApi import HubInstance, CreateFailedAlreadyExists
16+
17+
18+
def serialize_to_file(file, data):
19+
with open(file, "w") as f:
20+
json.dump(data, f, indent=3)
21+
22+
parser = argparse.ArgumentParser("Dump users from a Hub instance")
23+
parser.add_argument("base_filename", help="There will be two files dumped - one raw and one prepped to copy users to another Hub instance")
24+
args = parser.parse_args()
25+
26+
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
27+
28+
source_hub = HubInstance()
29+
30+
user_keys_to_delete = ['_meta', 'href', 'links']
31+
32+
users_to_copy = source_hub.get_users()
33+
34+
if 'totalCount' in users_to_copy and users_to_copy['totalCount'] > 0:
35+
logging.info("Dumping {} users from {}".format(users_to_copy['totalCount'], source_hub.config['baseurl']))
36+
assert 'items' in users_to_copy, "Should always be a list of items in a non-zero list of users"
37+
38+
user_data_raw = []
39+
user_data_prepped_to_copy = []
40+
41+
for user in users_to_copy['items']:
42+
if user['userName'] == 'sysadmin':
43+
continue
44+
# pprint(user)
45+
user_roles_response = source_hub.get_roles_for_user_or_group(user)
46+
if user_roles_response:
47+
user_roles = user_roles_response.json()
48+
else:
49+
user_roles = []
50+
51+
user_data_raw.append({
52+
'user': user, 'roles': user_roles
53+
})
54+
55+
user_copy_prepped_to_create = user.copy()
56+
for k in user_keys_to_delete:
57+
if k in user_copy_prepped_to_create:
58+
del user_copy_prepped_to_create[k]
59+
60+
# Need to add a password value to get Hub to create the user even
61+
# for EXTERNAL users
62+
if 'password' not in user_copy_prepped_to_create:
63+
user_copy_prepped_to_create['password'] = 'blackduck'
64+
65+
user_roles_to_create = [role['name'] for role in user_roles['items']]
66+
67+
user_data_prepped_to_copy.append({
68+
'user': user_copy_prepped_to_create, 'roles': user_roles_to_create
69+
})
70+
71+
raw_file = args.base_filename + ".raw"
72+
prepped_file = args.base_filename + ".prepped"
73+
74+
serialize_to_file(raw_file, user_data_raw)
75+
serialize_to_file(prepped_file, user_data_prepped_to_copy)
76+
else:
77+
logging.info("No users to dump")
78+
79+
80+

0 commit comments

Comments
 (0)