+ self.assert_my_gid()
+ return SfaServerProxy (url, self.private_key_filename(), self.my_gid_filename(),
+ verbose=self.verbose, timeout=self.timeout)
+
+ # now in some cases the self-signed is enough
+ def server_proxy_simple (self, url):
+ self.assert_self_signed_cert()
+ return SfaServerProxy (url, self.private_key_filename(), self.self_signed_cert_filename(),
+ verbose=self.verbose, timeout=self.timeout)
+
+ # this method can optionnally be invoked to ensure proper
+ # installation of the private key that belongs to this user
+ # installs private_key in working dir with expected name -- preserve mode
+ # typically user_private_key would be ~/.ssh/id_rsa
+ # xxx should probably check the 2 files are identical
+ def init_private_key_if_missing (self, user_private_key):
+ private_key_filename=self.private_key_filename()
+ if not os.path.isfile (private_key_filename):
+ key=self.plain_read(user_private_key)
+ self.plain_write(private_key_filename, key)
+ os.chmod(private_key_filename,os.stat(user_private_key).st_mode)
+ self.logger.debug("SfaClientBootstrap: Copied private key from %s into %s"%\
+ (user_private_key,private_key_filename))
+
+ #################### private details
+ # stupid stuff
+ def fullpath (self, file): return os.path.join (self.dir,file)
+
+ # the expected filenames for the various pieces
+ def private_key_filename (self):
+ return self.fullpath ("%s.pkey" % Xrn.unescape(self.hrn))
+ def self_signed_cert_filename (self):
+ return self.fullpath ("%s.sscert"%self.hrn)
+ def my_credential_filename (self):
+ return self.credential_filename (self.hrn, "user")
+ # the tests use sfi -u <pi-user>; meaning that the slice credential filename
+ # needs to keep track of the user too
+ def credential_filename (self, hrn, type):
+ if type in ['user']:
+ basename="%s.%s.cred"%(hrn,type)
+ else:
+ basename="%s-%s.%s.cred"%(self.hrn,hrn,type)
+ return self.fullpath (basename)
+ def slice_credential_filename (self, hrn):
+ return self.credential_filename(hrn,'slice')
+ def authority_credential_filename (self, hrn):
+ return self.credential_filename(hrn,'authority')
+ def my_gid_filename (self):
+ return self.gid_filename (self.hrn, "user")
+ def gid_filename (self, hrn, type):
+ return self.fullpath ("%s.%s.gid"%(hrn,type))
+ def my_pkcs12_filename (self):
+ return self.fullpath ("%s.p12"%self.hrn)
+
+# optimizing dependencies
+# originally we used classes GID or Credential or Certificate
+# like e.g.
+# return Credential(filename=self.my_credential()).save_to_string()
+# but in order to make it simpler to other implementations/languages..
+ def plain_read (self, filename):
+ infile=file(filename,"r")
+ result=infile.read()
+ infile.close()
+ return result
+
+ def plain_write (self, filename, contents):
+ outfile=file(filename,"w")
+ result=outfile.write(contents)
+ outfile.close()
+
+ def assert_filename (self, filename, kind):
+ if not os.path.isfile (filename):
+ raise IOError("Missing %s file %s"%(kind,filename))
+ return True
+
+ def assert_private_key (self):
+ return self.assert_filename (self.private_key_filename(),"private key")
+ def assert_self_signed_cert (self):
+ return self.assert_filename (self.self_signed_cert_filename(),"self-signed certificate")
+ def assert_my_credential (self):
+ return self.assert_filename (self.my_credential_filename(),"user's credential")
+ def assert_my_gid (self):
+ return self.assert_filename (self.my_gid_filename(),"user's GID")
+
+
+ # decorator to make up the other methods
+ def get_or_produce (filename_method, produce_method, validate_method=None):
+ # default validator returns true
+ def wrap (f):
+ def wrapped (self, *args, **kw):
+ filename=filename_method (self, *args, **kw)
+ if os.path.isfile ( filename ):
+ if not validate_method:
+ return filename
+ elif validate_method(self, filename):
+ return filename
+ else:
+ # remove invalid file
+ self.logger.warning ("Removing %s - has expired"%filename)
+ os.unlink(filename)
+ try:
+ produce_method (self, filename, *args, **kw)
+ return filename
+ except IOError:
+ raise
+ except :
+ error = sys.exc_info()[:2]
+ message="Could not produce/retrieve %s (%s -- %s)"%\
+ (filename,error[0],error[1])
+ self.logger.log_exc(message)
+ raise Exception(message)
+ return wrapped
+ return wrap
+
+ @get_or_produce (self_signed_cert_filename, self_signed_cert_produce)
+ def self_signed_cert (self): pass
+
+ @get_or_produce (my_credential_filename, my_credential_produce, validate_credential)
+ def my_credential (self): pass
+
+ @get_or_produce (my_gid_filename, my_gid_produce)
+ def my_gid (self): pass
+
+ @get_or_produce (my_pkcs12_filename, my_pkcs12_produce)
+ def my_pkcs12 (self): pass
+
+ @get_or_produce (credential_filename, credential_produce, validate_credential)
+ def credential (self, hrn, type): pass
+
+ @get_or_produce (slice_credential_filename, slice_credential_produce, validate_credential)
+ def slice_credential (self, hrn): pass
+
+ @get_or_produce (authority_credential_filename, authority_credential_produce, validate_credential)
+ def authority_credential (self, hrn): pass
+
+ @get_or_produce (gid_filename, gid_produce)
+ def gid (self, hrn, type ): pass
+
+
+ # get the credentials as strings, for inserting as API arguments
+ def my_credential_string (self):
+ self.my_credential()
+ return self.plain_read(self.my_credential_filename())
+ def slice_credential_string (self, hrn):
+ self.slice_credential(hrn)
+ return self.plain_read(self.slice_credential_filename(hrn))
+ def authority_credential_string (self, hrn):
+ self.authority_credential(hrn)
+ return self.plain_read(self.authority_credential_filename(hrn))
+
+ # for consistency
+ def private_key (self):
+ self.assert_private_key()
+ return self.private_key_filename()
+
+ def delegate_credential_string (self, original_credential, to_hrn, to_type='authority'):
+ """
+ sign a delegation credential to someone else
+
+ original_credential : typically one's user- or slice- credential to be delegated to s/b else
+ to_hrn : the hrn of the person that will be allowed to do stuff on our behalf
+ to_type : goes with to_hrn, usually 'user' or 'authority'
+
+ returns a string with the delegated credential
+
+ this internally uses self.my_gid()
+ it also retrieves the gid for to_hrn/to_type
+ and uses Credential.delegate()"""
+
+ # the gid and hrn of the object we are delegating
+ if isinstance (original_credential, str):
+ original_credential = Credential (string=original_credential)
+ original_gid = original_credential.get_gid_object()
+ original_hrn = original_gid.get_hrn()
+
+ if not original_credential.get_privileges().get_all_delegate():
+ self.logger.error("delegate_credential_string: original credential %s does not have delegate bit set"%original_hrn)
+ return
+
+ # the delegating user's gid
+ my_gid = self.my_gid()