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

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@7817
Revision 7817, 14.0 KB checked in by pjkersha, 9 years ago (diff)

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

  • major progress on independent OpenID Provider template. Requires some fixes to Yadis templates to complete.
  • 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
16import re
17from urlparse import urlunsplit
18from paste.script.templates import Template, var
19from paste.script.copydir import LaxTemplate
20
21_hostTuple = socket.gethostbyaddr(socket.gethostname())
22try:
23    # Get first alias from list if present
24    _hostname = _hostTuple[1][0]
25except IndexError:
26    # ... or default to hostname
27    _hostname = _hostTuple[0]
28   
29from ndg.saml.saml2.core import Issuer   
30
31
32class DoublePercentTemplate(string.Template):
33    """Alternative template uses '%%' instead of '$' to denote template
34    variables.  This is used because some NDG Security templates contain
35    '$' variables used for other purposes."""
36    delimiter = "%%"
37
38_MYPROXY_SERVER_LOCALID_XRD_ENTRY_TMPL = """<XRD>
39        <Service priority="10">
40            <Type>urn:esg:security:myproxy-service</Type>
41            <URI>%%{myproxyServerURI}</URI>
42            <LocalID>$user_url</LocalID>
43        </Service>
44    </XRD>
45"""
46
47_ATTRIBUTE_SERVICE_LOCALID_XRD_ENTRY_TMPL = """<XRD>
48        <Service priority="20">
49            <Type>urn:esg:security:attribute-service</Type>
50            <Type>urn:esg:security:attribute-service</Type>
51            <URI>%%{attributeServiceURI}</URI>
52            <LocalID>$user_url</LocalID>
53        </Service>
54    </XRD>
55"""
56
57_MYPROXY_SERVER_NONLOCALID_XRD_ENTRY_TMPL = """<XRD>
58        <Service priority="10">
59            <Type>urn:esg:security:myproxy-service</Type>
60            <URI>%%{myproxyServerURI}</URI>
61        </Service>
62    </XRD>
63"""
64
65_ATTRIBUTE_SERVICE_NONLOCALID_XRD_ENTRY_TMPL = """<XRD>
66        <Service priority="20">
67            <Type>urn:esg:security:attribute-service</Type>
68            <URI>%%{attributeServiceURI}</URI>
69        </Service>
70    </XRD>
71"""
72
73
74class ServicesTemplate(Template):
75    """Make a template containing all the Security Services available with
76    NDG Security.  These are provided together in one template but deployers
77    should consider adapting this and dividing up into separate WSGI apps
78    to suit
79    """
80    DEFAULT_PORT_NUM = 7443
81    DEFAULT_URI = urlunsplit(('https', _hostname, '', None, None))
82   
83    ATTRIBUTE_SERVICE_DEFAULT_MOUNT_POINT = '/AttributeService'
84    ATTRIBUTE_SERVICE_DEFAULT_ISSUER_NAME = '/O=Site A/CN=Attribute Authority'
85    ATTRIBUTE_SERVICE_DEFAULT_ISSUER_FORMAT = Issuer.X509_SUBJECT
86   
87    AUTHORISATION_SERVICE_DEFAULT_ISSUER_NAME = \
88        '/O=Site A/CN=Authorisation Service'
89    AUTHORISATION_SERVICE_DEFAULT_ISSUER_FORMAT = Issuer.X509_SUBJECT
90    AUTHORISATION_SERVICE_DEFAULT_MOUNT_POINT = '/AuthorisationService'
91   
92    MYPROXY_SERVER_LOCALID_XRD_ENTRY_TMPL = \
93        _MYPROXY_SERVER_LOCALID_XRD_ENTRY_TMPL
94   
95    ATTRIBUTE_SERVICE_LOCALID_XRD_ENTRY_TMPL = \
96        _ATTRIBUTE_SERVICE_LOCALID_XRD_ENTRY_TMPL
97
98    MYPROXY_SERVER_NONLOCALID_XRD_ENTRY_TMPL = \
99        _MYPROXY_SERVER_NONLOCALID_XRD_ENTRY_TMPL
100   
101    ATTRIBUTE_SERVICE_NONLOCALID_XRD_ENTRY_TMPL = \
102        _ATTRIBUTE_SERVICE_NONLOCALID_XRD_ENTRY_TMPL
103   
104   
105    _template_dir = 'services'
106    summary = ('NERC DataGrid Security services full deployment template '
107               'including the SAML Attribute and Authorisation Services, '
108               'OpenID Provider application, OpenID Relying Party and SSL '
109               'client authentication services')
110    vars = [
111        var('portNumber',
112            'Port number to run service on (applies for running with paster ONLY)',
113            default=DEFAULT_PORT_NUM),
114           
115        var('baseURI',
116            'Base URI for the service',
117            default=DEFAULT_URI),
118           
119        var('attributeServiceMountPoint',
120            'Mount point for Attribute Service',
121            ATTRIBUTE_SERVICE_DEFAULT_MOUNT_POINT),
122           
123        var('authorisationServiceMountPoint',
124            'Mount point for Authorisation Service',
125            AUTHORISATION_SERVICE_DEFAULT_MOUNT_POINT),
126           
127        var('attributeServiceIssuerName',
128            'SAML Issuer Name field for Attribute Service SAML responses',
129            ATTRIBUTE_SERVICE_DEFAULT_ISSUER_NAME),
130           
131        var('attributeServiceIssuerFormat',
132            'SAML Issuer Name field for Attribute Service SAML responses',
133            ATTRIBUTE_SERVICE_DEFAULT_ISSUER_FORMAT),
134           
135        var('authorisationServiceIssuerName',
136            'SAML Issuer Name field for Authorisation Service SAML responses',
137            AUTHORISATION_SERVICE_DEFAULT_ISSUER_NAME),
138           
139        var('authorisationServiceIssuerFormat',
140            'SAML Issuer Name field for Authorisation Service SAML responses',
141            AUTHORISATION_SERVICE_DEFAULT_ISSUER_FORMAT),
142
143        var('authkitCookieSecret', 
144            ('Cookie secret for AuthKit authentication middleware.  This value '
145             'MUST agree with the one used for the ini file of the application '
146             'to be secured'),
147            default=base64.b64encode(os.urandom(32))[:32]),
148
149        var('beakerSessionCookieSecret', 
150            'Secret for securing the OpenID Provider and SSL Client '
151            'authentication session cookie',
152            default=base64.b64encode(os.urandom(32))[:32]),
153           
154        var('openidRelyingPartyCookieSecret',
155            'Secret for securing OpenID Relying Party session cookie',
156            default=base64.b64encode(os.urandom(32))[:32]),
157           
158        var('myproxyServerURI',
159            'MyProxy Server address to advertise in OpenID Provider Yadis '
160            'document - defaults to omit this entry',
161            default=''),
162           
163        var('includeAttributeServiceInYadis',
164            'Include Attribute Service address in OpenID Provider Yadis '
165            'document',
166            default=True)
167        ]
168   
169    def __init__(self, *arg, **kw):
170        """Extend to enable custom setting for template substitution.  This
171        enables the special variable in service.ini_tmpl "userIdentifier" to
172        be ignored
173        """
174        self._laxTemplatePattern = LaxTemplate.pattern
175        LaxTemplate.pattern = re.compile(r"""
176        \%%(?:
177          (?P<escaped>\$)             |   # Escape sequence of two delimiters
178          (?P<named>[_a-z][_a-z0-9]*) |   # delimiter and a Python identifier
179          {(?P<braced>.*?)}           |   # delimiter and a braced identifier
180          (?P<invalid>)                   # Other ill-formed delimiter exprs
181        )
182        """)
183        super(ServicesTemplate, self).__init__(*arg, **kw)
184       
185    def __del__(self):
186        """Restore default setting for template pattern to its original value
187        """
188        LaxTemplate.pattern = self._laxTemplatePattern
189        _super = super(ServicesTemplate, self)
190        if hasattr(_super, "__del__"):
191            _super.__del__()
192
193    def pre(self, command, output_dir, vars):
194        '''Extend to enable substitutions for OpenID Provider Yadis templates''' 
195        vars['extraXrdEntries'] = ''
196       
197        attributeServiceURI = vars['baseURI'] + vars[
198                                'attributeServiceMountPoint'].lstrip('/')
199       
200        if vars['includeAttributeServiceInYadis']:
201            attributeServiceEntryTmpl = DoublePercentTemplate(
202                            self.__class__.ATTRIBUTE_SERVICE_XRD_ENTRY_TMPL)
203            vars['extraXrdEntries'] += attributeServiceEntryTmpl.substitute(
204                            attributeServiceURI=attributeServiceURI)
205
206        del vars['includeAttributeServiceInYadis']
207        if vars['myproxyServerURI']:
208            myProxyServerEntryTmpl = DoublePercentTemplate(
209                            self.__class__.MYPROXY_SERVER_XRD_ENTRY_TMPL)
210            vars['extraXrdEntries'] += myProxyServerEntryTmpl.substitute(
211                            myproxyServerURI=vars['myproxyServerURI'])
212       
213        del vars['myproxyServerURI']   
214        super(ServicesTemplate, self).pre(command, output_dir, vars)
215
216       
217class SecuredAppTemplate(Template):
218    """Create a template for a secured application with authentication and
219    authorisation filters"""
220   
221    _template_dir = 'secured_application'
222    summary = (
223        'Secure an application with NERC DataGrid Security '
224        'authentication and authorisation filters')
225    vars = [
226        var('hostname', 
227            ('Virtual host name to mount services on'),
228            default=_hostname),
229
230        var('authkitCookieSecret', 
231            ('Cookie secret for AuthKit authentication middleware (if using a '
232             'separate SSL based OpenID Relying Party then this value MUST '
233             'agree with the one used for that ini file'),
234            default=base64.b64encode(os.urandom(32))[:32]),
235
236        var('beakerSessionSecret', 
237            'Cookie secret for keeping security session state',
238            default=base64.b64encode(os.urandom(32))[:32])
239    ]
240
241
242class AttributeServiceTemplate(Template):
243    """Paster template for the SAML attribute service"""
244   
245    DEFAULT_MOUNT_POINT = '/AttributeService'
246    DEFAULT_ISSUER_NAME = 'O=NDG, OU=Security, CN=localhost'
247    DEFAULT_ISSUER_FORMAT = Issuer.X509_SUBJECT
248   
249    _template_dir = 'attributeservice'
250    summary = 'Create an NDG Security SAML Attribute Service'
251    vars = [
252        var('mountPoint', 
253            ('URI path to mount service i.e. https://myhost/<mountPoint>'),
254            default=DEFAULT_MOUNT_POINT),
255
256        var('issuerName', 
257            ('ID of this service used in SAML queries and responses'),
258            default=DEFAULT_ISSUER_NAME),
259
260        var('issuerFormat', 
261            ('Format of issuerName string; if using the default, ensure that '
262             'the issuerName value is a correctly formatted X.509 Subject '
263             'Name'),
264            default=DEFAULT_ISSUER_FORMAT)
265    ]
266   
267
268class AuthorisationServiceTemplate(Template):
269    """Paster template for the SAML authorisation service"""
270   
271    DEFAULT_MOUNT_POINT = '/AuthorisationService'
272    DEFAULT_ISSUER_NAME = 'O=NDG, OU=Security, CN=localhost'
273    DEFAULT_ISSUER_FORMAT = Issuer.X509_SUBJECT
274   
275    _template_dir = 'authorisationservice'
276    summary = 'Create an NDG Security Authorisation Service'
277    vars = [
278        var('mountPoint', 
279            ('URI path to mount service i.e. https://myhost/<mountPoint>'),
280            default=DEFAULT_MOUNT_POINT),
281
282        var('issuerName', 
283            ('ID of this service used in SAML queries and responses'),
284            default=DEFAULT_ISSUER_NAME),
285
286        var('issuerFormat', 
287            ('Format of issuerName string; if using the default, ensure that '
288             'the issuerName value is a correctly formatted X.509 Subject '
289             'Name'),
290            default=DEFAULT_ISSUER_FORMAT)
291    ]
292
293
294class OpenIDProviderTemplate(Template):
295    """Paster template for OpenID Provider service"""
296    _template_dir = 'openidprovider'
297    summary = 'Create an NDG Security OpenID Provider'
298   
299    DEFAULT_PORT_NUM = 7443
300    DEFAULT_URI = urlunsplit(('https', _hostname, '', None, None))
301   
302    MYPROXY_SERVER_LOCALID_XRD_ENTRY_TMPL = \
303        _MYPROXY_SERVER_LOCALID_XRD_ENTRY_TMPL
304   
305    ATTRIBUTE_SERVICE_LOCALID_XRD_ENTRY_TMPL = \
306        _ATTRIBUTE_SERVICE_LOCALID_XRD_ENTRY_TMPL
307
308    MYPROXY_SERVER_NONLOCALID_XRD_ENTRY_TMPL = \
309        _MYPROXY_SERVER_NONLOCALID_XRD_ENTRY_TMPL
310   
311    ATTRIBUTE_SERVICE_NONLOCALID_XRD_ENTRY_TMPL = \
312        _ATTRIBUTE_SERVICE_NONLOCALID_XRD_ENTRY_TMPL
313   
314    vars = [
315        var('portNumber',
316            'Port number to run service on (applies for running with paster ONLY)',
317            default=DEFAULT_PORT_NUM),
318           
319        var('baseURI',
320            'Base URI for the service',
321            default=DEFAULT_URI),
322
323        var('beakerSessionCookieSecret', 
324            'Secret for securing the OpenID Provider and SSL Client '
325            'authentication session cookie',
326            default=base64.b64encode(os.urandom(32))[:32]),
327           
328        var('myproxyServerURI',
329            'MyProxy Server address to advertise in OpenID Provider Yadis '
330            'document - defaults to omit this entry',
331            default=''),
332           
333        var('attributeServiceURI',
334            'Attribute Service address to advertise in OpenID Provider Yadis '
335            'document - defaults to omit this entry',
336            default='')
337        ]
338   
339    def template_renderer(self, content, vars, filename=None):
340        """Alternative renderer defined to enable use of '%%' prefix for template
341        variables.  NDG Security ini files already use '$' for other variables
342       
343        @param content: template content
344        @type content: string
345        @param vars: variables to substituted into the template
346        @type vars: dict
347        @return: content with all variables substituted for
348        @rtype: string
349        """
350        tmpl = DoublePercentTemplate(content)
351        return tmpl.substitute(**vars)
352
353    def pre(self, command, output_dir, vars):
354        '''Extend to enable substitutions for OpenID Provider Yadis templates
355        and fix log file path setting''' 
356        vars['outputDir'] = os.path.abspath(output_dir)
357
358        vars['yadisExtraXrdEntries'] = ''
359        vars['serveryadisExtraXrdEntries'] = ''
360       
361        if vars['attributeServiceURI']:
362            attributeServiceEntryTmpl = DoublePercentTemplate(
363                            self.__class__.MYPROXY_SERVER_LOCALID_XRD_ENTRY_TMPL)
364            vars['extraXrdEntries'] += attributeServiceEntryTmpl.substitute(
365                            attributeServiceURI=vars['attributeServiceURI'])
366
367        del vars['attributeServiceURI']
368        if vars['myproxyServerURI']:
369            myProxyServerEntryTmpl = DoublePercentTemplate(
370                            self.__class__.MYPROXY_SERVER_XRD_ENTRY_TMPL)
371            vars['extraXrdEntries'] += myProxyServerEntryTmpl.substitute(
372                            myproxyServerURI=vars['myproxyServerURI'])
373       
374        del vars['myproxyServerURI']   
375        super(OpenIDProviderTemplate, self).pre(command, output_dir, vars)
376
377
Note: See TracBrowser for help on using the repository browser.