source: TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/paster_templates/template.py @ 7828

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/paster_templates/template.py@7828
Revision 7828, 16.4 KB checked in by pjkersha, 10 years ago (diff)

Incomplete - task 16: NDG Security 2.x.x - incl. updated Paster templates

  • improved ndg.security.server.attributeauthority.SQLAlchemyAttributeInterface so that it can retrieve attributes and set them into custom SAML Attribute Value types. Previously it only supported xs:string type values. Custom types can be set by specifying a special callback set in the samlAttributeSqlQuery property or via the equivalent ini file option. - See site-a.ini
  • Unit test site-a attribute authority now uses the SQLite test user db instead of fixed constants from the unit test base class. This makes it easier to customise into a paster ini template.
  • Property svn:executable set to *
  • Property svn:keywords set to Id
Line 
1"""NDG Security Paster template classes
2
3NERC DataGrid Project
4"""
5__author__ = "P J Kershaw"
6__date__ = "20/10/2010"
7__copyright__ = "(C) 2010 Science and Technology Facilities Council"
8__license__ = "BSD - see top-level directory for LICENSE file"
9__contact__ = "Philip.Kershaw@stfc.ac.uk"
10__revision__ = "$Id$"
11
12import os
13import socket
14import base64
15import string
16from urlparse import urlunsplit, urlparse
17from paste.script.templates import Template, var
18
19_hostTuple = socket.gethostbyaddr(socket.gethostname())
20try:
21    # Get first alias from list if present
22    _hostname = _hostTuple[1][0]
23except IndexError:
24    # ... or default to hostname
25    _hostname = _hostTuple[0]
26   
27from ndg.saml.saml2.core import Issuer   
28
29
30class DoublePercentTemplate(string.Template):
31    """Alternative template uses '%%' instead of '$' to denote template
32    variables.  This is used because some NDG Security templates contain
33    '$' variables used for other purposes."""
34    delimiter = "%%"
35
36
37"""@var _MYPROXY_SERVER_LOCALID_XRD_ENTRY_TMPL: Yadis XRDS entry for a MyProxy
38server endpoint.  This entry also include a localID $user_url which the OpenID
39Provider application code will fill out at runtime.
40@type _MYPROXY_SERVER_LOCALID_XRD_ENTRY_TMPL: ndg.security.server.paster_templates.template.DoublePercentTemplate
41"""
42_MYPROXY_SERVER_LOCALID_XRD_ENTRY_TMPL = DoublePercentTemplate("""<XRD>
43        <Service priority="10">
44            <Type>urn:esg:security:myproxy-service</Type>
45            <URI>%%{myproxyServerURI}</URI>
46            <LocalID>$user_url</LocalID>
47        </Service>
48    </XRD>
49""")
50
51"""@var _ATTRIBUTE_SERVICE_LOCALID_XRD_ENTRY_TMPL: Yadis XRDS entry for an
52Attribute Service endpoint.  This entry also include a localID $user_url which
53the OpenID Provider application code will fill out at runtime.
54@type _ATTRIBUTE_SERVICE_LOCALID_XRD_ENTRY_TMPL: ndg.security.server.paster_templates.template.DoublePercentTemplate
55"""
56_ATTRIBUTE_SERVICE_LOCALID_XRD_ENTRY_TMPL = DoublePercentTemplate("""<XRD>
57        <Service priority="20">
58            <Type>urn:esg:security:attribute-service</Type>
59            <Type>urn:esg:security:attribute-service</Type>
60            <URI>%%{attributeServiceURI}</URI>
61            <LocalID>$user_url</LocalID>
62        </Service>
63    </XRD>
64""")
65
66"""@var _MYPROXY_SERVER_NONLOCALID_XRD_ENTRY_TMPL: Yadis XRDS entry for a
67MyProxy server endpoint.  No localID entry is included as this template is for
68use with the serveryadis.xml_tmpl which applies to requests where the specific
69identity is not provided.
70@type _MYPROXY_SERVER_NONLOCALID_XRD_ENTRY_TMPL: ndg.security.server.paster_templates.template.DoublePercentTemplate
71"""
72_MYPROXY_SERVER_NONLOCALID_XRD_ENTRY_TMPL = DoublePercentTemplate("""<XRD>
73        <Service priority="10">
74            <Type>urn:esg:security:myproxy-service</Type>
75            <URI>%%{myproxyServerURI}</URI>
76        </Service>
77    </XRD>
78""")
79
80"""@var _ATTRIBUTE_SERVICE_NONLOCALID_XRD_ENTRY_TMPL: Yadis XRDS entry for an
81Attribute Service endpoint.  No localID entry is included as this template is
82for use with the serveryadis.xml_tmpl which applies to requests where the
83specific identity is not provided.
84@type _ATTRIBUTE_SERVICE_NONLOCALID_XRD_ENTRY_TMPL: ndg.security.server.paster_templates.template.DoublePercentTemplate
85"""
86_ATTRIBUTE_SERVICE_NONLOCALID_XRD_ENTRY_TMPL = DoublePercentTemplate("""<XRD>
87        <Service priority="20">
88            <Type>urn:esg:security:attribute-service</Type>
89            <URI>%%{attributeServiceURI}</URI>
90        </Service>
91    </XRD>
92""")
93
94
95class ServicesTemplate(Template):
96    """Make a template containing all the Security Services available with
97    NDG Security.  These are provided together in one template but deployers
98    should consider adapting this and dividing up into separate WSGI apps
99    to suit
100    """
101    DEFAULT_URI = urlunsplit(('https', _hostname, '', None, None))
102   
103    ATTRIBUTE_SERVICE_DEFAULT_MOUNT_POINT = '/AttributeService'
104    ATTRIBUTE_SERVICE_DEFAULT_ISSUER_NAME = '/O=Site A/CN=Attribute Authority'
105    ATTRIBUTE_SERVICE_DEFAULT_ISSUER_FORMAT = Issuer.X509_SUBJECT
106   
107    AUTHORISATION_SERVICE_DEFAULT_ISSUER_NAME = \
108        '/O=Site A/CN=Authorisation Service'
109    AUTHORISATION_SERVICE_DEFAULT_ISSUER_FORMAT = Issuer.X509_SUBJECT
110    AUTHORISATION_SERVICE_DEFAULT_MOUNT_POINT = '/AuthorisationService'   
111   
112    _template_dir = 'services'
113    summary = ('NERC DataGrid Security services full deployment template '
114               'including the SAML Attribute and Authorisation Services, '
115               'OpenID Provider application, OpenID Relying Party and SSL '
116               'client authentication services')
117    vars = [
118        var('baseURI',
119            'Base URI for the service(s) [with no trailing slash]',
120            default=DEFAULT_URI),
121           
122        var('attributeServiceMountPoint',
123            'Mount point for Attribute Service',
124            ATTRIBUTE_SERVICE_DEFAULT_MOUNT_POINT),
125           
126        var('authorisationServiceMountPoint',
127            'Mount point for Authorisation Service',
128            AUTHORISATION_SERVICE_DEFAULT_MOUNT_POINT),
129           
130        var('attributeServiceIssuerName',
131            'SAML Issuer Name field for Attribute Service SAML responses',
132            ATTRIBUTE_SERVICE_DEFAULT_ISSUER_NAME),
133           
134        var('attributeServiceIssuerFormat',
135            'SAML Issuer Name field for Attribute Service SAML responses',
136            ATTRIBUTE_SERVICE_DEFAULT_ISSUER_FORMAT),
137           
138        var('authorisationServiceIssuerName',
139            'SAML Issuer Name field for Authorisation Service SAML responses',
140            AUTHORISATION_SERVICE_DEFAULT_ISSUER_NAME),
141           
142        var('authorisationServiceIssuerFormat',
143            'SAML Issuer Name field for Authorisation Service SAML responses',
144            AUTHORISATION_SERVICE_DEFAULT_ISSUER_FORMAT),
145
146        var('authkitCookieSecret', 
147            ('Cookie secret for AuthKit authentication middleware.  This value '
148             'MUST agree with the one used for the ini file of the application '
149             'to be secured'),
150            default=base64.b64encode(os.urandom(32))[:32]),
151
152        var('beakerSessionCookieSecret', 
153            'Secret for securing the OpenID Provider and SSL Client '
154            'authentication session cookie',
155            default=base64.b64encode(os.urandom(32))[:32]),
156           
157        var('openidRelyingPartyCookieSecret',
158            'Secret for securing OpenID Relying Party session cookie',
159            default=base64.b64encode(os.urandom(32))[:32]),
160           
161        var('myproxyServerURI',
162            'MyProxy Server address to advertise in OpenID Provider Yadis '
163            'document - defaults to omit this entry',
164            default=''),
165           
166        var('includeAttributeServiceInYadis',
167            'Include Attribute Service address in OpenID Provider Yadis '
168            'document',
169            default=True)
170        ]
171   
172    def template_renderer(self, content, vars, filename=None):
173        """Alternative renderer defined to enable use of '%%' prefix for template
174        variables.  NDG Security ini files already use '$' for other variables
175       
176        @param content: template content
177        @type content: string
178        @param vars: variables to substituted into the template
179        @type vars: dict
180        @return: content with all variables substituted for
181        @rtype: string
182        """
183        tmpl = DoublePercentTemplate(content)
184        return tmpl.substitute(**vars)
185   
186    def pre(self, command, output_dir, vars):
187        '''Extend to enable substitutions for OpenID Provider Yadis templates,
188        port number and fix log file path setting
189       
190        @param command: command to create template
191        @type command:
192        @param output_dir: output directory for template file(s)
193        @type output_dir: string
194        @param vars: variables to be substituted into template
195        @type vars: dict
196        ''' 
197       
198        # This sets the log file path
199        vars['outputDir'] = os.path.abspath(output_dir)
200
201        # Cut out port number from base URI
202        uriParts = urlparse(vars['baseURI'])
203        netlocLastElem = uriParts.netloc.split(':')[-1]
204        if netlocLastElem.isdigit():
205            vars['portNumber'] = netlocLastElem
206        else:
207            vars['portNumber'] = ''
208           
209        vars['yadisExtraXrdEntries'] = ''
210        vars['serveryadisExtraXrdEntries'] = ''
211       
212        attributeServiceURI = vars['baseURI'] + vars[
213                                'attributeServiceMountPoint'].lstrip('/')
214       
215        # Attribute Service entry added if flag was set
216        if vars['includeAttributeServiceInYadis']:
217            # yadis.xml_tmpl entry
218            vars['yadisExtraXrdEntries'
219                 ] += _ATTRIBUTE_SERVICE_LOCALID_XRD_ENTRY_TMPL.substitute(
220                        attributeServiceURI=attributeServiceURI)
221
222            # serveryadis.xml_tmpl entry
223            vars['serveryadisExtraXrdEntries'
224                 ] += _ATTRIBUTE_SERVICE_NONLOCALID_XRD_ENTRY_TMPL.substitute(
225                        attributeServiceURI=attributeServiceURI)
226
227        del vars['includeAttributeServiceInYadis']
228       
229        # MyProxy Server entry added if an endpoint was specified
230        if vars['myproxyServerURI']:
231            # yadis.xml_tmpl entry
232            vars['yadisExtraXrdEntries'
233                 ] += _MYPROXY_SERVER_LOCALID_XRD_ENTRY_TMPL.substitute(
234                            myproxyServerURI=vars['myproxyServerURI'])       
235           
236            vars['serveryadisExtraXrdEntries'
237                 ] += _MYPROXY_SERVER_NONLOCALID_XRD_ENTRY_TMPL.substitute(
238                        myproxyServerURI=vars['myproxyServerURI'])
239        del vars['myproxyServerURI']   
240       
241        super(ServicesTemplate, self).pre(command, output_dir, vars)
242
243       
244class SecuredAppTemplate(Template):
245    """Create a template for a secured application with authentication and
246    authorisation filters"""
247   
248    _template_dir = 'secured_application'
249    summary = (
250        'Secure an application with NERC DataGrid Security '
251        'authentication and authorisation filters')
252    vars = [
253        var('hostname', 
254            ('Virtual host name to mount services on'),
255            default=_hostname),
256
257        var('authkitCookieSecret', 
258            ('Cookie secret for AuthKit authentication middleware (if using a '
259             'separate SSL based OpenID Relying Party then this value MUST '
260             'agree with the one used for that ini file'),
261            default=base64.b64encode(os.urandom(32))[:32]),
262
263        var('beakerSessionSecret', 
264            'Cookie secret for keeping security session state',
265            default=base64.b64encode(os.urandom(32))[:32])
266    ]
267
268
269class AttributeServiceTemplate(Template):
270    """Paster template for the SAML attribute service"""
271   
272    DEFAULT_PORT = 5000
273    DEFAULT_MOUNT_POINT = '/AttributeService'
274    DEFAULT_ISSUER_NAME = 'O=NDG, OU=Security, CN=localhost'
275    DEFAULT_ISSUER_FORMAT = Issuer.X509_SUBJECT
276   
277    _template_dir = 'attributeservice'
278    summary = 'Create an NDG Security SAML Attribute Service'
279    vars = [
280        var('portNumber',
281            'Port number for service to listen on [applies to running with '
282            'paster ONLY]',
283            default=DEFAULT_PORT),
284           
285        var('mountPoint', 
286            ('URI path to mount service i.e. https://myhost/<mountPoint>'),
287            default=DEFAULT_MOUNT_POINT),
288
289        var('issuerName', 
290            ('ID of this service used in SAML queries and responses'),
291            default=DEFAULT_ISSUER_NAME),
292
293        var('issuerFormat', 
294            ('Format of issuerName string; if using the default, ensure that '
295             'the issuerName value is a correctly formatted X.509 Subject '
296             'Name'),
297            default=DEFAULT_ISSUER_FORMAT)
298    ]
299   
300
301class AuthorisationServiceTemplate(Template):
302    """Paster template for the SAML authorisation service"""
303   
304    DEFAULT_MOUNT_POINT = '/AuthorisationService'
305    DEFAULT_ISSUER_NAME = 'O=NDG, OU=Security, CN=localhost'
306    DEFAULT_ISSUER_FORMAT = Issuer.X509_SUBJECT
307   
308    _template_dir = 'authorisationservice'
309    summary = 'Create an NDG Security Authorisation Service'
310    vars = [
311        var('mountPoint', 
312            ('URI path to mount service i.e. https://myhost/<mountPoint>'),
313            default=DEFAULT_MOUNT_POINT),
314
315        var('issuerName', 
316            ('ID of this service used in SAML queries and responses'),
317            default=DEFAULT_ISSUER_NAME),
318
319        var('issuerFormat', 
320            ('Format of issuerName string; if using the default, ensure that '
321             'the issuerName value is a correctly formatted X.509 Subject '
322             'Name'),
323            default=DEFAULT_ISSUER_FORMAT)
324    ]
325
326
327class OpenIDProviderTemplate(Template):
328    """Paster template for OpenID Provider service"""
329    _template_dir = 'openidprovider'
330    summary = 'Create an NDG Security OpenID Provider'
331   
332    DEFAULT_URI = urlunsplit(('https', _hostname, '', None, None))
333   
334    vars = [
335        var('baseURI',
336            'Base URI for the service [with no trailing slash]',
337            default=DEFAULT_URI),
338
339        var('beakerSessionCookieSecret', 
340            'Secret for securing the OpenID Provider and SSL Client '
341            'authentication session cookie',
342            default=base64.b64encode(os.urandom(32))[:32]),
343           
344        var('myproxyServerURI',
345            'MyProxy Server address to advertise in OpenID Provider Yadis '
346            'document - defaults to omit this entry',
347            default=''),
348           
349        var('attributeServiceURI',
350            'Attribute Service address to advertise in OpenID Provider Yadis '
351            'document - defaults to omit this entry',
352            default='')
353        ]
354   
355    def template_renderer(self, content, vars, filename=None):
356        """Alternative renderer defined to enable use of '%%' prefix for template
357        variables.  NDG Security ini files already use '$' for other variables
358       
359        @param content: template content
360        @type content: string
361        @param vars: variables to substituted into the template
362        @type vars: dict
363        @return: content with all variables substituted for
364        @rtype: string
365        """
366        tmpl = DoublePercentTemplate(content)
367        return tmpl.substitute(**vars)
368
369    def pre(self, command, output_dir, vars):
370        '''Extend to enable substitutions for OpenID Provider Yadis templates,
371        port number and fix log file path setting
372       
373        @param command: command to create template
374        @type command:
375        @param output_dir: output directory for template file(s)
376        @type output_dir: string
377        @param vars: variables to be substituted into template
378        @type vars: dict
379        ''' 
380       
381        # This sets the log file path
382        vars['outputDir'] = os.path.abspath(output_dir)
383
384        # Cut out port number from base URI
385        uriParts = urlparse(vars['baseURI'])
386        netlocLastElem = uriParts.netloc.split(':')[-1]
387        if netlocLastElem.isdigit():
388            vars['portNumber'] = netlocLastElem
389        else:
390            vars['portNumber'] = ''
391
392        # Set Yadis XRDS entries
393        vars['yadisExtraXrdEntries'] = ''
394        vars['serveryadisExtraXrdEntries'] = ''
395       
396        # Attribute Service entry added if an endpoint was specified
397        if vars['attributeServiceURI']:
398            # yadis.xml_tmpl entry
399            vars['yadisExtraXrdEntries'
400                 ] += _ATTRIBUTE_SERVICE_LOCALID_XRD_ENTRY_TMPL.substitute(
401                        attributeServiceURI=vars['attributeServiceURI'])
402
403            # serveryadis.xml_tmpl entry
404            vars['serveryadisExtraXrdEntries'
405                 ] += _ATTRIBUTE_SERVICE_NONLOCALID_XRD_ENTRY_TMPL.substitute(
406                        attributeServiceURI=vars['attributeServiceURI'])
407
408        del vars['attributeServiceURI']
409       
410        if vars['myproxyServerURI']:
411            # yadis.xml_tmpl entry
412            vars['yadisExtraXrdEntries'
413                 ] += _MYPROXY_SERVER_LOCALID_XRD_ENTRY_TMPL.substitute(
414                            myproxyServerURI=vars['myproxyServerURI'])       
415           
416            vars['serveryadisExtraXrdEntries'
417                 ] += _MYPROXY_SERVER_NONLOCALID_XRD_ENTRY_TMPL.substitute(
418                        myproxyServerURI=vars['myproxyServerURI'])
419                         
420        del vars['myproxyServerURI'] 
421         
422        super(OpenIDProviderTemplate, self).pre(command, output_dir, vars)
423
424
Note: See TracBrowser for help on using the repository browser.