From 3d2095eb4405726f1f3fe84469dfee7b68f47c16 Mon Sep 17 00:00:00 2001 From: Tom Mitchell Date: Mon, 22 May 2017 16:24:07 -0400 Subject: [PATCH 1/3] Remove trailing whitespace --- bin/portal_utils/orbit_interface.py | 64 ++++++++++++++--------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/bin/portal_utils/orbit_interface.py b/bin/portal_utils/orbit_interface.py index fbcefdb1..d7fce0fc 100644 --- a/bin/portal_utils/orbit_interface.py +++ b/bin/portal_utils/orbit_interface.py @@ -43,15 +43,15 @@ class CODES: # Means portal tried to add a user that already exists. Handled explicitly. ERROR1 = 'ERROR 1: UID and OU and DC match' - # Means trying to change project. + # Means trying to change project. # Shouldn't happen, but code checks for this ERROR2 = 'ERROR 2: UID and DC match but OU is different' - # Member username exists from different authority. + # Member username exists from different authority. # Code tries to pick a different username. ERROR3 = 'ERROR 3: UID matches but DC and OU are different' - # Seems to imply that group ou must be unique for both + # Seems to imply that group ou must be unique for both # local and portal created groups? Huh? # FIXME FIXME ERROR4 = 'ERROR 4: UID and OU match but DC is different' @@ -69,7 +69,7 @@ class CODES: # Handled explicitly in deleteProject ERROR8 = 'ERROR 8: Group/project not deleted because it contains admin(s):' - # Theoretically could happen from changeProject if I'm trying to move a + # Theoretically could happen from changeProject if I'm trying to move a # user not created by the portal to a different project. Shouldn't happen. ERROR9 = 'ERROR 9: Cannot move users: different DCs' @@ -82,7 +82,7 @@ class CODES: # Malformed LDIF ERROR12 = 'ERROR 12: Missing objectClass attribute (organizationalUnit/organizationalRole/organizationalUnit) for' - # Attempt to create a group without an admin, or with unknown admin + # Attempt to create a group without an admin, or with unknown admin ERROR17 = 'ERROR 17: Missing PI entry' # Tried to create a group that already exists. @@ -98,29 +98,29 @@ class CODES: # Malformed LDIF. ERROR30 = 'ERROR 30: Missing username (UID)' - # FIXME: I need to handle this (see comments below). + # FIXME: I need to handle this (see comments below). # This means I tried to add a user to a group that doesn't exist. ERROR31 = 'ERROR 31: Organization does not exist for this user. Missing organization LDIF entry' - # Malformed LDIF. Not all portal users must have an email address. + # Malformed LDIF. Not all portal users must have an email address. ERROR32 = 'ERROR 32: Missing users email address' # Malformed LDIF. Note we explicitly require users have an SSH key. ERROR33 = "ERROR 33: Missing user's sshpublickey:" - ALL = [ERROR1, ERROR2, ERROR3, ERROR4, ERROR5, ERROR5, + ALL = [ERROR1, ERROR2, ERROR3, ERROR4, ERROR5, ERROR5, ERROR6, ERROR7, ERROR8, ERROR9, ERROR10, ERROR11, - ERROR12, ERROR17, ERROR20, ERROR21, ERROR22, + ERROR12, ERROR17, ERROR20, ERROR21, ERROR22, ERROR30, ERROR31, ERROR32, ERROR33] -# Class to manage interactions with ORBIT through +# Class to manage interactions with ORBIT through # Delegated Account Management API class ORBIT_Interface: def __init__(self, base_orbit_url): self._base_orbit_url = base_orbit_url self._DEVNULL = open(os.devnull, 'w') - + MAX_TIMEOUT = "20" # Number of seconds to wait for a curl command to complete @@ -139,7 +139,7 @@ def get_curl_output(self, query_url): try: out_file, out_filename = tempfile.mkstemp() raw_curl_output = \ - subprocess.check_output(["timeout", self.MAX_TIMEOUT, "curl", "-k", query_url], + subprocess.check_output(["timeout", self.MAX_TIMEOUT, "curl", "-k", query_url], stderr = out_file ) os.unlink(out_filename) @@ -152,9 +152,9 @@ def get_curl_output(self, query_url): return raw_curl_output # Invoke an ORBIT REST API call - # Create url, make call via curl + # Create url, make call via curl # and exit if an (untolerated) error returned - def invoke_orbit_method(self, method, args, + def invoke_orbit_method(self, method, args, tolerated_error_codes = []): url = "%s/%s?%s" % (self._base_orbit_url, method, args) output = self.get_curl_output(url) @@ -162,12 +162,12 @@ def invoke_orbit_method(self, method, args, if code and code not in tolerated_error_codes: syslog("Error in %s call: %s" % (method, output)) sys.exit(code) - + # Add ORBIT user to ORBIT group # NOTE: No error trying to add a user to a group to which it already exists def add_user_to_group(self, group_name, user_name): - self.invoke_orbit_method("addMemberToGroup", + self.invoke_orbit_method("addMemberToGroup", "groupname=%s&username=%s" % \ (group_name, user_name)) @@ -175,23 +175,23 @@ def add_user_to_group(self, group_name, user_name): def remove_user_from_group(self, group_name, user_name): self.invoke_orbit_method("removeMemberFromGroup", "groupname=%s&username=%s" % \ - (group_name, user_name), + (group_name, user_name), [CODES.ERROR5]) # Change ORBIT group admin def change_group_admin(self, group_name, admin_name): - self.invoke_orbit_method("changeGroupAdmin", + self.invoke_orbit_method("changeGroupAdmin", "groupname=%s&username=%s" % \ (group_name, admin_name)) # Enable ORBIT user def enable_user(self, user_name): - self.invoke_orbit_method("enableUser", + self.invoke_orbit_method("enableUser", "username=%s" % user_name, [CODES.ERROR5, CODES.ERROR6]) # Disable ORBIT user def disable_user(self, user_name): - self.invoke_orbit_method("disableUser", + self.invoke_orbit_method("disableUser", "username=%s" % user_name, [CODES.ERROR6, CODES.ERROR5]) # Delete ORBIT group @@ -242,8 +242,8 @@ def parse_group_members(self, orbit_info_raw): # Save group/admin/user data in LDIF def saveUser(self, user_ldif_data): - - save_user_url = "%s/saveUser" % self._base_orbit_url + + save_user_url = "%s/saveUser" % self._base_orbit_url out_file, out_filename = tempfile.mkstemp() os.write(out_file, user_ldif_data) @@ -253,9 +253,9 @@ def saveUser(self, user_ldif_data): output = "" try: err_file, err_filename = tempfile.mkstemp() - output = subprocess.check_output(["timeout", self.MAX_TIMEOUT, - "curl", "-k", "-PUT", "-H", - "Content-type: multipart/form-data", + output = subprocess.check_output(["timeout", self.MAX_TIMEOUT, + "curl", "-k", "-PUT", "-H", + "Content-type: multipart/form-data", "-F", ldif_arg, save_user_url], stderr=err_file) os.unlink(err_filename) @@ -273,7 +273,7 @@ def saveUser(self, user_ldif_data): sys.exit(error_code) os.unlink(out_filename) - + #---------------------------------------------------------------------- # Routines to create LDIF for project/group, user/member and admin #---------------------------------------------------------------------- @@ -318,10 +318,10 @@ def ldif_for_group(self, group_name, group_description): return group_ldif # LDIF for defining user - def ldif_for_user(self, user_name, group_name, user_prettyname, - user_givenname, user_email, user_sn, user_ssh_keys, + def ldif_for_user(self, user_name, group_name, user_prettyname, + user_givenname, user_email, user_sn, user_ssh_keys, user_group_description, user_irodsname): - + irods_entry = "" if user_irodsname: irods_entry = "iRODSusername: %s\n" % user_irodsname @@ -332,7 +332,7 @@ def ldif_for_user(self, user_name, group_name, user_prettyname, if i > 0: prefix = "%s%d" % (prefix, i+1) ssh_entries = ssh_entries + \ ("%s: %s\n" % (prefix, user_ssh_keys[i])) - + user_ldif_template = "# LDIF for user %s \n" + \ "dn: %s\n" + \ "cn: %s\n" + \ @@ -352,10 +352,8 @@ def ldif_for_user(self, user_name, group_name, user_prettyname, "objectclass: hostObject\n" + \ "objectclass: ldapPublicKey\n" user_ldif = user_ldif_template % \ - (user_name, self.ldif_dn_for_user(user_name, group_name), + (user_name, self.ldif_dn_for_user(user_name, group_name), user_prettyname, user_givenname, user_email, user_sn, irods_entry, ssh_entries, user_name, user_group_description) return user_ldif - - From db5f5a6208c2308ca08073455743dc265a0258fb Mon Sep 17 00:00:00 2001 From: Tom Mitchell Date: Tue, 23 May 2017 11:57:42 -0400 Subject: [PATCH 2/3] Fix an encoding error in geni-sync-wireless Use UTF-8 encoding when writing LDIF records to file so that wide characters are encoded properly. --- CHANGES.md | 2 ++ bin/portal_utils/orbit_interface.py | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index b601dd7f..aa046203 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,8 @@ ([#1794](https://github.com/GENI-NSF/geni-portal/issues/1794)) * Add .php to RSpec related redirects ([#1797](https://github.com/GENI-NSF/geni-portal/issues/1797)) +* Fix a UTF-8 encoding error in geni-sync-wireless + ([#1799](https://github.com/GENI-NSF/geni-portal/issues/1799)) ## Installation Notes diff --git a/bin/portal_utils/orbit_interface.py b/bin/portal_utils/orbit_interface.py index d7fce0fc..83cb5a85 100644 --- a/bin/portal_utils/orbit_interface.py +++ b/bin/portal_utils/orbit_interface.py @@ -28,6 +28,7 @@ # Interface routines for conecting to ORBIT Delegated Account Management API #---------------------------------------------------------------------- +import io import os import subprocess import sys @@ -246,8 +247,9 @@ def saveUser(self, user_ldif_data): save_user_url = "%s/saveUser" % self._base_orbit_url out_file, out_filename = tempfile.mkstemp() - os.write(out_file, user_ldif_data) - os.close(out_file) + utf8_file = io.open(out_file, mode='w', encoding='utf8') + utf8_file.write(user_ldif_data.decode('utf-8')) + utf8_file.close() ldif_arg = "ldif=@%s" % out_filename output = "" From 24b6f2f1170f410d464bcfe3bb2bf8841139cebc Mon Sep 17 00:00:00 2001 From: Tom Mitchell Date: Tue, 23 May 2017 12:06:46 -0400 Subject: [PATCH 3/3] Fix pycodestyle warnings --- bin/portal_utils/orbit_interface.py | 62 +++++++++++++++-------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/bin/portal_utils/orbit_interface.py b/bin/portal_utils/orbit_interface.py index 83cb5a85..9c68e2bb 100644 --- a/bin/portal_utils/orbit_interface.py +++ b/bin/portal_utils/orbit_interface.py @@ -1,8 +1,8 @@ #!/usr/bin/env python # -*- Mode: python -*- # -#---------------------------------------------------------------------- -# Copyright (c) 2015-2016 Raytheon BBN Technologies +# ---------------------------------------------------------------------- +# Copyright (c) 2015-2017 Raytheon BBN Technologies # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and/or hardware specification (the "Work") to @@ -22,11 +22,11 @@ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS # IN THE WORK. -#---------------------------------------------------------------------- +# ---------------------------------------------------------------------- -#---------------------------------------------------------------------- +# ---------------------------------------------------------------------- # Interface routines for conecting to ORBIT Delegated Account Management API -#---------------------------------------------------------------------- +# ---------------------------------------------------------------------- import io import os @@ -57,7 +57,6 @@ class CODES: # FIXME FIXME ERROR4 = 'ERROR 4: UID and OU match but DC is different' - # Handled explicitly when trying to deleteUser, changeLeader, changeProject ERROR5 = 'ERROR 5: Unknown username:' @@ -114,6 +113,7 @@ class CODES: ERROR12, ERROR17, ERROR20, ERROR21, ERROR22, ERROR30, ERROR31, ERROR32, ERROR33] + # Class to manage interactions with ORBIT through # Delegated Account Management API class ORBIT_Interface: @@ -122,15 +122,14 @@ def __init__(self, base_orbit_url): self._base_orbit_url = base_orbit_url self._DEVNULL = open(os.devnull, 'w') - MAX_TIMEOUT = "20" # Number of seconds to wait for a curl command to complete - + MAX_TIMEOUT = "20" # Number of seconds to wait for a curl command to complete # Does given string contain one of the defined errors? # If so, return the error, otherwise, return None def find_error_code(self, str): for cd in CODES.ALL: if str.find(cd) >= 0: - return cd; + return cd return None # Return value from CURL on URL @@ -141,14 +140,14 @@ def get_curl_output(self, query_url): out_file, out_filename = tempfile.mkstemp() raw_curl_output = \ subprocess.check_output(["timeout", self.MAX_TIMEOUT, "curl", "-k", query_url], - stderr = out_file + stderr=out_file ) os.unlink(out_filename) except subprocess.CalledProcessError as e: error_text = open(out_filename, 'r').read() os.unlink(out_filename) - syslog("Error invoking CURL on %s: Error %s Msg %s" % \ - (query_url, e.returncode, error_text)) + syslog("Error invoking CURL on %s: Error %s Msg %s" % + (query_url, e.returncode, error_text)) sys.exit(e.returncode) return raw_curl_output @@ -156,7 +155,7 @@ def get_curl_output(self, query_url): # Create url, make call via curl # and exit if an (untolerated) error returned def invoke_orbit_method(self, method, args, - tolerated_error_codes = []): + tolerated_error_codes=[]): url = "%s/%s?%s" % (self._base_orbit_url, method, args) output = self.get_curl_output(url) code = self.find_error_code(output) @@ -164,40 +163,42 @@ def invoke_orbit_method(self, method, args, syslog("Error in %s call: %s" % (method, output)) sys.exit(code) - # Add ORBIT user to ORBIT group # NOTE: No error trying to add a user to a group to which it already exists def add_user_to_group(self, group_name, user_name): self.invoke_orbit_method("addMemberToGroup", - "groupname=%s&username=%s" % \ - (group_name, user_name)) + "groupname=%s&username=%s" % + (group_name, user_name)) # Remove ORBIT user to ORBIT group def remove_user_from_group(self, group_name, user_name): self.invoke_orbit_method("removeMemberFromGroup", - "groupname=%s&username=%s" % \ - (group_name, user_name), + "groupname=%s&username=%s" % + (group_name, user_name), [CODES.ERROR5]) # Change ORBIT group admin def change_group_admin(self, group_name, admin_name): self.invoke_orbit_method("changeGroupAdmin", - "groupname=%s&username=%s" % \ - (group_name, admin_name)) + "groupname=%s&username=%s" % + (group_name, admin_name)) # Enable ORBIT user def enable_user(self, user_name): self.invoke_orbit_method("enableUser", - "username=%s" % user_name, [CODES.ERROR5, CODES.ERROR6]) + "username=%s" % user_name, + [CODES.ERROR5, CODES.ERROR6]) # Disable ORBIT user def disable_user(self, user_name): self.invoke_orbit_method("disableUser", - "username=%s" % user_name, [CODES.ERROR6, CODES.ERROR5]) + "username=%s" % user_name, + [CODES.ERROR6, CODES.ERROR5]) # Delete ORBIT group def delete_group(self, group_name): - self.invoke_orbit_method("deleteGroup", "groupname=%s"% group_name, [CODES.ERROR7]) + self.invoke_orbit_method("deleteGroup", "groupname=%s" % group_name, + [CODES.ERROR7]) # Get ORBIT group/user info @@ -225,7 +226,7 @@ def parse_group_user_info(self, orbit_info_raw): for group_node in group_nodes: group_name = group_node.getAttribute('groupname') group_admin = group_node.getAttribute('admin') - groups[group_name] = {'admin' : group_admin, 'users' : []} + groups[group_name] = {'admin': group_admin, 'users': []} for user_node in user_nodes: user_name = user_node.getAttribute('username') users.append(user_name) @@ -263,8 +264,8 @@ def saveUser(self, user_ldif_data): os.unlink(err_filename) except subprocess.CalledProcessError as e: error_text = open(err_filename, 'r'). read() - syslog("Error invoking curl LDIF saveUser command: %s: Error %s Msg %s" \ - (save_user_url, e.returncode, error_text)) + syslog("Error invoking curl LDIF saveUser command: %s: Error %s Msg %s" + (save_user_url, e.returncode, error_text)) os.unlink(err_fileame) sys.exit(e.returncode) @@ -276,9 +277,9 @@ def saveUser(self, user_ldif_data): os.unlink(out_filename) -#---------------------------------------------------------------------- +# ---------------------------------------------------------------------- # Routines to create LDIF for project/group, user/member and admin -#---------------------------------------------------------------------- +# ---------------------------------------------------------------------- # DN base element defining ch.geni.net namespace def ldif_dn_base(self): @@ -331,12 +332,13 @@ def ldif_for_user(self, user_name, group_name, user_prettyname, ssh_entries = "" for i in range(len(user_ssh_keys)): prefix = "sshpublickey" - if i > 0: prefix = "%s%d" % (prefix, i+1) + if i > 0: + prefix = "%s%d" % (prefix, i+1) ssh_entries = ssh_entries + \ ("%s: %s\n" % (prefix, user_ssh_keys[i])) user_ldif_template = "# LDIF for user %s \n" + \ - "dn: %s\n" + \ + "dn: %s\n" + \ "cn: %s\n" + \ "givenname: %s\n" + \ "mail: %s\n" + \