<commit_before>#----------------------------------------------------------------------
# Copyright (c) 2010 <NAME>
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and/or hardware specification (the "Work") to
# deal in the Work without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Work, and to permit persons to whom the Work
# is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Work.
#
# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# 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.
#----------------------------------------------------------------------
"""
Reference GENI GCF Clearinghouse. Uses SFA Certificate and credential objects.
NOTE it requires a user cert at startup to get the full certificate chain.
Run from gch.py
Will produce signed user credentials from a GID, return a
(hard coded) list of aggregates, and create a new Slice Credential.

"""

import logging
import os
import uuid

from SecureXMLRPCServer import SecureXMLRPCServer
from am import CredentialVerifier
import sfa.trust.gid as gid
import sfa.trust.certificate as cert
import sfa.trust.credential as cred
import sfa.trust.rights as rights

# Substitute eg "openflow//stanford ch"
SLICEPUBID_PREFIX = "geni.net//gpo//gcf"
SLICE_GID_SUBJ = "gcf.slice"

USER_CRED_LIFE = 86400
SLICE_CRED_LIFE = 3600

# The list of Aggregates that this Clearinghouse knows about
# should be defined in the geni_aggregates file
# ListResources will refer the client to these aggregates
# Clearinghouse.runserver currently does the register_aggregate_pair
# calls for each row in that file
# but this should be doable dynamically
# Some sample pairs:
# GPOMYPLC = ('urn:publicid:IDN+plc:gpo1+authority+sa',
#             'http://myplc1.gpolab.bbn.com:12348')
# TESTGCFAM = ('urn:publicid:IDN+geni.net:gpo+authority+gcf', 
#              'http://127.0.0.1:8001') 
# OTHERGPOMYPLC = ('urn:publicid:IDN+plc:gpo+authority+site2',
#                    'http://172.16.17.32:12348')
# ELABINELABAM = ('urn:publicid:IDN+elabinelab.geni.emulab.net',
#                 'https://myboss.elabinelab.geni.emulab.net:443/protogeni/xmlrpc/am')

class ClearinghouseServer(object):
    """The public API for the Clearinghouse.  This class provides the
    XMLRPC interface and invokes a delegate for all the operations.

    """

    def __init__(self, delegate):
        self._delegate = delegate
        
    def GetVersion(self):
        return self._delegate.GetVersion()

    def Resolve(self, urn):
        return self._delegate.Resolve(urn)
    


class SampleClearinghouseServer(ClearinghouseServer):
    """Add Additional functionality that is not part of the geni API
    specification.

    """

    def __init__(self, delegate):
        self._delegate = delegate
        
    def CreateSlice(self, urn=None):
        return self._delegate.CreateSlice(urn_req=urn)

    def DeleteSlice(self, urn):
        return self._delegate.DeleteSlice(urn)

    def ListAggregates(self):
        return self._delegate.ListAggregates()
    
    def CreateUserCredential(self, cert):
        return self._delegate.CreateUserCredential(cert)


class Clearinghouse(object):

    def __init__(self):
        self.logger = logging.getLogger('gch')
        self.slices = {}
        self.aggs = []

    def register_aggregate_pair(self, aggpair):
        '''Add an aggregate URN and URL pair to the known set. URL is unverified'''
        if aggpair is None:
            self.logger.debug('Null aggpair ignored')
            return
        if len(aggpair) != 2:
            self.logger.debug('Len %d aggpair ignored', len(aggpair))
            return
        if aggpair[0] is None or aggpair[0].strip() == "":
            self.logger.debug('Empty URN in Aggpair - ignore')
            return
        if aggpair[1] is None or aggpair[1].strip() == "":
            self.logger.debug('Empty URL in Aggpair for URN %s: ignore', aggpair[0])
            return

        # TODO: Avoid dupes, confirm the AM is reachable, ?
        # Real CH would require an AM contact, AM cert, ?
        self.logger.info("Registering AM %r", aggpair)
        self.aggs.append(aggpair)
        
        # ca_certs is a file of 1 ca cert possibly, preferably a dir of several
    def runserver(self, addr, keyfile=None, certfile=None,
                  ca_certs=None, user_cert=None, aggfile=None):
        """Run the clearinghouse server."""
        self.keyfile = keyfile
        self.certfile = certfile
        self.usercert = user_cert
        

        # Error check the keyfile, certfile, usercert all exist
        if keyfile is None or not os.path.isfile(os.path.expanduser(keyfile)):
            raise Exception("Missing CH key file %s" % keyfile)
        if certfile is None or not os.path.isfile(os.path.expanduser(certfile)):
            raise Exception("Missing CH cert file %s" % certfile)
        if user_cert is None or not os.path.isfile(os.path.expanduser(user_cert)):
            raise Exception("Missing user cert file %s" % user_cert)

        if ca_certs is None:
            raise Exception("Missing CA cert(s) arg")

        if not os.path.exists(os.path.expanduser(ca_certs)):
            raise Exception("Missing CA cert(s): %s" % ca_certs)

        # Load up the aggregates
        print aggfile
        if os.path.isfile(aggfile):
            for line in file(aggfile):
                spl = line.strip().split(',')
                if len(spl) == 2:
                    self.register_aggregate_pair((spl[0].strip(),spl[1].strip()))
        self.logger.info("%d Aggregate Managers registered", len(self.aggs))

        # This is the arg to _make_server
        ca_certs_onefname = CredentialVerifier.getCAsFileFromDir(ca_certs)

        # This is used below by CreateSlice
        self.ca_cert_fnames = []
        if os.path.isfile(os.path.expanduser(ca_certs)):
            self.ca_cert_fnames = [os.path.expanduser(ca_certs)]
        elif os.path.isdir(os.path.expanduser(ca_certs)):
            self.ca_cert_fnames = [os.path.join(os.path.expanduser(ca_certs), name) for name in os.listdir(os.path.expanduser(ca_certs)) if name != CredentialVerifier.CATEDCERTSFNAME]

        # Create the xmlrpc server, load the rootkeys and do the ssl thing.
        self._server = self._make_server(addr, keyfile, certfile,
                                         ca_certs_onefname)
        self._server.register_instance(SampleClearinghouseServer(self))
        self.logger.info('GENI CH Listening on port %d...' % (addr[1]))
        self._server.serve_forever()

    def _make_server(self, addr, keyfile=None, certfile=None,
                     ca_certs=None):
        """Creates the XML RPC server."""
        # ca_certs is a file of concatenated certs
        return SecureXMLRPCServer(addr, keyfile=keyfile, certfile=certfile,
                                  ca_certs=ca_certs)

    def GetVersion(self):
        self.logger.info("Called GetVersion")
        version = dict()
        version['geni_api'] = 1<commit_msg>take out a print<commit_after>#----------------------------------------------------------------------
# Copyright (c) 2010 <NAME>
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and/or hardware specification (the "Work") to
# deal in the Work without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Work, and to permit persons to whom the Work
# is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Work.
#
# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# 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.
#----------------------------------------------------------------------
"""
Reference GENI GCF Clearinghouse. Uses SFA Certificate and credential objects.
NOTE it requires a user cert at startup to get the full certificate chain.
Run from gch.py
Will produce signed user credentials from a GID, return a
(hard coded) list of aggregates, and create a new Slice Credential.

"""

import logging
import os
import uuid

from SecureXMLRPCServer import SecureXMLRPCServer
from am import CredentialVerifier
import sfa.trust.gid as gid
import sfa.trust.certificate as cert
import sfa.trust.credential as cred
import sfa.trust.rights as rights

# Substitute eg "openflow//stanford ch"
SLICEPUBID_PREFIX = "geni.net//gpo//gcf"
SLICE_GID_SUBJ = "gcf.slice"

USER_CRED_LIFE = 86400
SLICE_CRED_LIFE = 3600

# The list of Aggregates that this Clearinghouse knows about
# should be defined in the geni_aggregates file
# ListResources will refer the client to these aggregates
# Clearinghouse.runserver currently does the register_aggregate_pair
# calls for each row in that file
# but this should be doable dynamically
# Some sample pairs:
# GPOMYPLC = ('urn:publicid:IDN+plc:gpo1+authority+sa',
#             'http://myplc1.gpolab.bbn.com:12348')
# TESTGCFAM = ('urn:publicid:IDN+geni.net:gpo+authority+gcf', 
#              'http://127.0.0.1:8001') 
# OTHERGPOMYPLC = ('urn:publicid:IDN+plc:gpo+authority+site2',
#                    'http://172.16.17.32:12348')
# ELABINELABAM = ('urn:publicid:IDN+elabinelab.geni.emulab.net',
#                 'https://myboss.elabinelab.geni.emulab.net:443/protogeni/xmlrpc/am')

class ClearinghouseServer(object):
    """The public API for the Clearinghouse.  This class provides the
    XMLRPC interface and invokes a delegate for all the operations.

    """

    def __init__(self, delegate):
        self._delegate = delegate
        
    def GetVersion(self):
        return self._delegate.GetVersion()

    def Resolve(self, urn):
        return self._delegate.Resolve(urn)
    


class SampleClearinghouseServer(ClearinghouseServer):
    """Add Additional functionality that is not part of the geni API
    specification.

    """

    def __init__(self, delegate):
        self._delegate = delegate
        
    def CreateSlice(self, urn=None):
        return self._delegate.CreateSlice(urn_req=urn)

    def DeleteSlice(self, urn):
        return self._delegate.DeleteSlice(urn)

    def ListAggregates(self):
        return self._delegate.ListAggregates()
    
    def CreateUserCredential(self, cert):
        return self._delegate.CreateUserCredential(cert)


class Clearinghouse(object):

    def __init__(self):
        self.logger = logging.getLogger('gch')
        self.slices = {}
        self.aggs = []

    def register_aggregate_pair(self, aggpair):
        '''Add an aggregate URN and URL pair to the known set. URL is unverified'''
        if aggpair is None:
            self.logger.debug('Null aggpair ignored')
            return
        if len(aggpair) != 2:
            self.logger.debug('Len %d aggpair ignored', len(aggpair))
            return
        if aggpair[0] is None or aggpair[0].strip() == "":
            self.logger.debug('Empty URN in Aggpair - ignore')
            return
        if aggpair[1] is None or aggpair[1].strip() == "":
            self.logger.debug('Empty URL in Aggpair for URN %s: ignore', aggpair[0])
            return

        # TODO: Avoid dupes, confirm the AM is reachable, ?
        # Real CH would require an AM contact, AM cert, ?
        self.logger.info("Registering AM %r", aggpair)
        self.aggs.append(aggpair)
        
        # ca_certs is a file of 1 ca cert possibly, preferably a dir of several
    def runserver(self, addr, keyfile=None, certfile=None,
                  ca_certs=None, user_cert=None, aggfile=None):
        """Run the clearinghouse server."""
        self.keyfile = keyfile
        self.certfile = certfile
        self.usercert = user_cert
        

        # Error check the keyfile, certfile, usercert all exist
        if keyfile is None or not os.path.isfile(os.path.expanduser(keyfile)):
            raise Exception("Missing CH key file %s" % keyfile)
        if certfile is None or not os.path.isfile(os.path.expanduser(certfile)):
            raise Exception("Missing CH cert file %s" % certfile)
        if user_cert is None or not os.path.isfile(os.path.expanduser(user_cert)):
            raise Exception("Missing user cert file %s" % user_cert)

        if ca_certs is None:
            raise Exception("Missing CA cert(s) arg")

        if not os.path.exists(os.path.expanduser(ca_certs)):
            raise Exception("Missing CA cert(s): %s" % ca_certs)

        # Load up the aggregates
        #print aggfile
        if os.path.isfile(aggfile):
            for line in file(aggfile):
                spl = line.strip().split(',')
                if len(spl) == 2:
                    self.register_aggregate_pair((spl[0].strip(),spl[1].strip()))
        self.logger.info("%d Aggregate Managers registered from aggregates file %r", len(self.aggs), aggfile)

        # This is the arg to _make_server
        ca_certs_onefname = CredentialVerifier.getCAsFileFromDir(ca_certs)

        # This is used below by CreateSlice
        self.ca_cert_fnames = []
        if os.path.isfile(os.path.expanduser(ca_certs)):
            self.ca_cert_fnames = [os.path.expanduser(ca_certs)]
        elif os.path.isdir(os.path.expanduser(ca_certs)):
            self.ca_cert_fnames = [os.path.join(os.path.expanduser(ca_certs), name) for name in os.listdir(os.path.expanduser(ca_certs)) if name != CredentialVerifier.CATEDCERTSFNAME]

        # Create the xmlrpc server, load the rootkeys and do the ssl thing.
        self._server = self._make_server(addr, keyfile, certfile,
                                         ca_certs_onefname)
        self._server.register_instance(SampleClearinghouseServer(self))
        self.logger.info('GENI CH Listening on port %d...' % (addr[1]))
        self._server.serve_forever()

    def _make_server(self, addr, keyfile=None, certfile=None,
                     ca_certs=None):
        """Creates the XML RPC server."""
        # ca_certs is a file of concatenated certs
        return SecureXMLRPCServer(addr, keyfile=keyfile, certfile=certfile,
                                  ca_certs=ca_certs)

    def GetVersion(self):
        self.logger.info("Called GetVersion")
        version = dict()
        version['geni_api'] = 1
{'fraction_non_alphanumeric': 0.11026566087241718, 'fraction_numerical': 0.00787143325680551, 'mean_word_length': 2.676392572944297, 'pattern_counts': {'":': 4, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 4, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6386579', 'n_tokens_mistral': 4647, 'n_tokens_neox': 4398, 'n_words': 1387}