Ignore:
Timestamp:
26/10/12 22:44:00 (8 years ago)
Author:
pjkersha
Message:

Version now fully integrated with Python OnlineCA service. This is an alternative to using MyProxy? to create certificates made possible by using the ContrailOnlineCAService package, a Python CA implementation. The configuration is in the 'slcs' example. This configuration also uses the independent OAuthResourceServerMiddleware, middleware which applies the necessary checks on the access token before passing on the request to the underlying application. In this case, the OnlineCA.

Location:
trunk/ndg_oauth/ndg_oauth_server/ndg/oauth/server
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/ndg_oauth/ndg_oauth_server/ndg/oauth/server/examples/slcs/slcs_server_app.ini

    r8196 r8236  
    1515smtp_server = localhost 
    1616error_email_from = paste@localhost 
     17 
     18# These are common variables referenced by more than one section below.  They 
     19# set the paths for the OAuth services and the protected resources (just one in 
     20# this case - the OnlineCA's certificate issuing path) 
     21oauth_server_basepath = /oauth 
     22onlineca_issue_certpath = %(oauth_server_basepath)s/certificate/ 
     23 
     24# The OAuth client to this service will request a resource on behalf of a user 
     25# based on an access token passed.  The resource server checks the token looking 
     26# it up in cached session information.  This session also holds the id of the  
     27# user who granted the token.  This id can be made available from the resource  
     28# server to the downstream application being protected.  In this case, this is  
     29# the OnlineCA service.  The OnlineCA needs the id in order to create the  
     30# correct certificate subject for the certificate to be issued. 
     31claimed_userid_environ_key = oauth_granting_userid 
    1732 
    1833beakerSessionKeyName = beaker.session.oauth2server 
     
    103118#oauth2server.access_token_type=bearer 
    104119#oauth2server.authorization_grant_lifetime=600 
    105 oauth2server.base_url_path=/oauth 
     120oauth2server.base_url_path=%(oauth_server_basepath)s 
    106121#oauth2server.certificate_request_parameter=certificate_request 
    107122# Allowed values: certificate (default) or none. 
     
    130145[filter:OAuth2ResourceServerFilter] 
    131146paste.filter_app_factory = ndg.oauth.server.wsgi.resource_server:Oauth2ResourceServerMiddleware.filter_app_factory 
    132 oauth2.resource_server.resource_uripaths: /certificate/ 
     147 
     148# Sets which paths are protected by OAuth.  In this example, the OnlineCA's 
     149# certificate issuing service 
     150oauth2.resource_server.resource_uripaths: %(onlineca_issue_certpath)s 
    133151     
     152# Scope required to access this resource.  More than one value can be set.   
     153# Values should be space delimited.  In this case, the value has been set to the 
     154# path of the certificate issuing path for the OnlineCA but this is just a 
     155# convenient value.  Any arbitrary string could have been set. 
     156oauth2.resource_server.required_scope: https://localhost:5000/oauth/certificate/ 
     157 
     158# Set the userid of the delegator as a key in environ.  This is useful for 
     159# access by the downstream app that the resource server middleware is  
     160# protecting.  In this case, the OnlineCA service. 
     161oauth2.resource_server.claimed_userid_environ_key: %(claimed_userid_environ_key)s 
     162 
    134163[app:OnlineCaApp] 
    135 paste.app_factory = onlineca.server.wsgi.app:OnlineCaApp.app_factory 
     164paste.app_factory = contrail.security.onlineca.server.wsgi.app:OnlineCaApp.app_factory 
    136165 
    137166# Set an alternative prefix for settings - default is 'onlineca.server.' 
     
    139168 
    140169# Path to CA Python class constructor or factory function 
    141 onlineca.server.ca_class_factory_path: onlineca.server.impl:CertificateAuthorityImpl 
     170onlineca.server.ca_class_factory_path: contrail.security.onlineca.server.impl:CertificateAuthorityImpl 
    142171 
    143172# onlineca.server.ca_class.* values correspond to settings for the CA class. 
     
    161190 
    162191# Template to set the form for the certificate subject name for output  
    163 # certificates.  This can reference any key name set in environ - in this case, 
    164 # 'REMOTE_USER' 
    165 onlineca.server.cert_subject_name_template: /O=NDG/OU=Security/CN=$REMOTE_USER 
     192# certificates. 
     193onlineca.server.cert_subject_name_template: /O=NDG/OU=Security/CN=$%(claimed_userid_environ_key)s 
    166194 
    167195# URI path for certificate issuing endpoint. e.g. if online ca app is mounted 
     
    172200# 
    173201# Default path is /certificate/ 
    174 #onlineca.server.issue_cert_uripath: /issue-cert/ 
     202onlineca.server.issue_cert_uripath: %(onlineca_issue_certpath)s 
    175203 
    176204# URI path for trustroots retrieval endpoint.  The default path is 
  • trunk/ndg_oauth/ndg_oauth_server/ndg/oauth/server/lib/authorize/authorizer_storing_identifier.py

    r8030 r8236  
    3535        self.lifetime = lifetime 
    3636        self.user_identifier_env_key = kw.get('user_identifier_env_key') 
    37         self.user_identifier_grant_data_key = kw.get('user_identifier_grant_data_key') 
     37        self.user_identifier_grant_data_key = kw.get( 
     38                                            'user_identifier_grant_data_key') 
    3839 
    3940    def generate_authorization_grant(self, auth_request, request): 
     
    5657        user_identifier = request.environ.get(self.user_identifier_env_key) 
    5758        if not user_identifier: 
    58             log.error('Could not find user identifier key "%s" in environ', self.user_identifier_env_key) 
    59             raise OauthException('server_error', 'Authorization grant could not be created') 
     59            log.error('Could not find user identifier key "%s" in environ',  
     60                      self.user_identifier_env_key) 
     61            raise OauthException('server_error',  
     62                                 'Authorization grant could not be created') 
    6063 
    6164        code = uuid.uuid4().hex 
     65        additional_data = {self.user_identifier_grant_data_key: user_identifier} 
    6266        grant = AuthorizationGrant(code, auth_request, self.lifetime, 
    63                                    additional_data={self.user_identifier_grant_data_key: user_identifier}) 
    64         return (grant, code) 
     67                                   additional_data=additional_data) 
     68        return grant, code 
  • trunk/ndg_oauth/ndg_oauth_server/ndg/oauth/server/wsgi/oauth2_server.py

    r8196 r8236  
    305305            return (None, url) 
    306306         
    307         return (client_authorized, None) 
     307        return client_authorized, None 
    308308 
    309309    def _make_client_authorization_url(self, req): 
  • trunk/ndg_oauth/ndg_oauth_server/ndg/oauth/server/wsgi/resource_server.py

    r8196 r8236  
    1515 
    1616from ndg.oauth.server.wsgi.oauth2_server import Oauth2ServerMiddleware 
     17from ndg.oauth.server.lib.authorization_server import AuthorizationServer 
    1718 
    1819log = logging.getLogger(__name__) 
     
    4041    RESOURCE_URIPATHS_OPTNAME = 'resource_uripaths' 
    4142     
     43    CLAIMED_USER_ID_ENVIRON_KEY_OPTNAME = 'claimed_userid_environ_key' 
     44    DEFAULT_CLAIMED_USER_ID_ENVIRON_KEYNAME = \ 
     45        'oauth.resource_server.claimed_userid' 
     46     
    4247    AUTHORISATION_SERVER_ENVIRON_KEYNAME = \ 
    4348        Oauth2ServerMiddleware.AUTHORISATION_SERVER_ENVIRON_KEYNAME 
    4449         
     50    __slots__ = ( 
     51        '_app', 
     52        '__authorization_server', 
     53        'claimed_userid_environ_key', 
     54        '__resource_uripaths', 
     55        '__required_scope' 
     56    ) 
    4557    def __init__(self, app): 
    4658        self._app = app 
    47         self._authorization_server = None 
    48         self.match_scope_to_client_dn = False 
     59        self.__authorization_server = None 
     60        self.claimed_userid_environ_key = \ 
     61            self.__class__.DEFAULT_CLAIMED_USER_ID_ENVIRON_KEYNAME 
    4962        self.__resource_uripaths = [] 
     63         
     64        # Scope for this resource - multiple space delimited scope values may 
     65        # be set 
     66        self.__required_scope = None 
    5067         
    5168    @classmethod 
     
    92109            raise TypeError('Expecting single string or space-separated URI ' 
    93110                            'paths or an iterable; got %r instead' % type(val)) 
    94              
     111      
     112    @property 
     113    def authorization_server(self): 
     114        return self.__authorization_server 
     115     
     116    @authorization_server.setter 
     117    def authorization_server(self, val): 
     118        if not isinstance(val, AuthorizationServer): 
     119            raise TypeError('Expecting %r type for "authorization_server" ' 
     120                            'attribute; got %r instead' % (AuthorizationServer,  
     121                                                           type(val))) 
     122        self.__authorization_server = val 
     123      
     124    @property 
     125    def required_scope(self): 
     126        return self.__required_scope 
     127     
     128    @required_scope.setter 
     129    def required_scope(self, val): 
     130        if not isinstance(val, basestring): 
     131            raise TypeError('Expecting string type for "required_scope" ' 
     132                            'attribute; got %r instead' % type(val)) 
     133        self.__required_scope = val  
     134                        
    95135    def __call__(self, environ, start_response): 
    96136        '''Apply validation of access token for configured resource paths 
     
    103143        request = Request(environ) 
    104144         
    105         self._authorization_server = environ.get( 
     145        self.authorization_server = environ.get( 
    106146                            self.__class__.AUTHORISATION_SERVER_ENVIRON_KEYNAME) 
    107         if self._authorization_server is None: 
    108             raise Oauth2ResourceServerMiddlewareConfigError( 
    109                 'No %r key to authorisation server set in environ' % 
    110                     self.__class__.AUTHORISATION_SERVER_ENVIRON_KEYNAME) 
    111147         
    112148        if self._match_uripath(request.path_info): 
    113             self.request_resource(request, start_response) 
     149            return self.request_resource(request, start_response) 
    114150        else: 
    115151            return self._app(environ, start_response) 
     
    133169                  "path %r", request.path_info) 
    134170 
    135         status = httplib.OK 
    136         content_dict ={} 
    137          
    138         if self.match_scope_to_client_dn: 
    139             provided_scope = request.environ.get(self.CERT_DN_ENVIRON_KEY) 
    140             if provided_scope: 
    141                 log.debug("Found certificate DN: %s", provided_scope) 
    142             else: 
    143                 # Client must be authenticated - no other error should be  
    144                 # included in this case. 
    145                 status = httplib.UNAUTHORIZED 
    146                 content_dict['error'] = ( 
    147                     "Client certificate %r subject required to match with " 
    148                     "scope but none set") % provided_scope 
    149                      
    150                 log.error(content_dict['error']) 
    151         else: 
    152             provided_scope = None 
    153          
    154171        # Check the token 
    155         if status == httplib.OK:     
    156             status, error = self._authorization_server.get_registered_token( 
     172        token, status, error = self.authorization_server.get_registered_token( 
    157173                                                    request,  
    158                                                     scope=provided_scope)[1:] 
    159             if error: 
    160                 content_dict.setdefault('error', error) 
    161             else: 
    162                 return None  # signal to caller that validation succeeded 
    163              
    164         response = json.dumps(content_dict) 
    165         headers = [ 
    166             ('Content-Type', 'application/json; charset=UTF-8'), 
    167             ('Cache-Control', 'no-store'), 
    168             ('Content-length', str(len(response))), 
    169             ('Pragma', 'no-store') 
    170         ] 
    171         status_str = "%d %s" % (status, httplib.responses[status]) 
    172         start_response(status_str, headers) 
    173         return [response] 
     174                                                    scope=self.required_scope) 
     175        if not error: 
     176            request.environ[self.claimed_userid_environ_key 
     177                    ] = token.grant.additional_data.get('user_identifier') 
     178                             
     179            return self._app(request.environ, start_response) 
     180        else: 
     181            status = httplib.OK 
     182            content_dict ={} 
     183            content_dict.setdefault('error', error) 
     184                         
     185            response = json.dumps(content_dict) 
     186            headers = [ 
     187                ('Content-Type', 'application/json; charset=UTF-8'), 
     188                ('Cache-Control', 'no-store'), 
     189                ('Content-length', str(len(response))), 
     190                ('Pragma', 'no-store') 
     191            ] 
     192            status_str = "%d %s" % (status, httplib.responses[status]) 
     193            start_response(status_str, headers) 
     194            return [response] 
    174195     
    175196    def _match_uripath(self, path): 
Note: See TracChangeset for help on using the changeset viewer.