Projet

Général

Profil

Télécharger (4,6 ko) Statistiques
| Branche: | Tag: | Révision:

mandayejs / mandayejs / mandaye / utils.py @ c23f4a3b

1
# mandayejs - saml reverse proxy
2
# Copyright (C) 2015  Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
import os
17
import re
18
import json
19
import subprocess
20
import logging
21
import multiprocessing
22
import urlparse
23

    
24
from django.conf import settings
25
from django.shortcuts import resolve_url
26

    
27
from Cookie import SimpleCookie
28

    
29

    
30
logger = logging.getLogger(__name__)
31

    
32

    
33
def run(send_end, data, script):
34
    phantom = subprocess.Popen([
35
        settings.PHANTOM_JS_BINARY,
36
        '--ignore-ssl-errors=yes', '--ssl-protocol=any',
37
        os.path.join(settings.BASE_DIR, 'mandayejs', script)],
38
        close_fds=True,
39
        stdin=subprocess.PIPE,
40
        stdout=subprocess.PIPE
41
    )
42
    stdout, stderr = phantom.communicate(json.dumps(data))
43

    
44
    try:
45
        output = re.search('<mandayejs>(.*?)</mandayejs>', stdout, re.DOTALL)
46
        if not output:
47
            raise ValueError
48
        stdout = output.group(1)
49
        result = json.loads(stdout)
50
    except (ValueError,):
51
        result = {"result": "json_error"}
52
        logger.error("invalid json: %s" % stdout)
53

    
54
    if result.get('stderr'):
55
        logger.warning(result['stderr'])
56
    if result.get('error'):
57
        logger.error('Error occured: %s' % result.get('reason'))
58

    
59
    send_end.send(result)
60
    send_end.close()
61

    
62

    
63
def exec_phantom(data, script='do_login.js'):
64
    recv_end, send_end = multiprocessing.Pipe(False)
65
    process = multiprocessing.Process(target=run, args=(send_end, data, script))
66
    process.start()
67

    
68
    if recv_end.poll(settings.PHANTOM_JS_TIMEOUT):
69
        result = recv_end.recv()
70
        recv_end.close()
71
    else:
72
        process.terminate()
73
        send_end.close()
74
        # Don't log locators, they may contain credentials (passwords)
75
        context = {k: v for k, v in data.items() if k != 'locators'}
76
        logger.error("PhantomJS process timeout, context: %s" % context)
77
        result = {'result': 'timeout'}
78

    
79
    return result
80

    
81

    
82
def cookie_builder(headers):
83
    """Build Cookies from list of headers
84
    """
85
    cookie = SimpleCookie()
86
    for header in headers:
87
        cookie.load('; '.join(header.values()).encode('ascii'))
88

    
89
    return cookie
90

    
91

    
92
def get_logout_info(request):
93
    """Returns phantomjs logout prerequis
94
    """
95
    from mandayejs.applications import get_app_settings
96
    app_settings = get_app_settings()
97

    
98
    data = {}
99
    data['logout_locator'] = getattr(app_settings, 'SITE_LOGOUT_LOCATOR')
100
    data['address'] = request.build_absolute_uri(resolve_url('home'))
101
    forced_logout_scheme = getattr(settings, 'PHANTOM_JS_LOGOUT_SCHEME')
102
    if forced_logout_scheme:
103
        url = urlparse.urlparse(data['address'])
104
        url = url._replace(scheme=forced_logout_scheme)
105
        data['address'] = url.geturl()
106
    cookies = SimpleCookie(request.META.get('HTTP_COOKIE'))
107
    domain = request.META.get('SERVER_NAME')
108

    
109
    # Phantomjs Cookies Format
110
    data['cookies'] = [{
111
        'name': key,
112
        'value': value.value,
113
        'domain': domain,
114
        'path': '/'
115
    } for key, value in cookies.items()]
116

    
117
    return data
118

    
119

    
120
def get_password_field():
121
    """Return name of the password field
122
    """
123
    from mandayejs.applications import get_app_settings
124
    app_settings = get_app_settings()
125
    try:
126
        field_name = [field.get('name') for field in app_settings.SITE_LOCATORS
127
                      if field.get('kind') == 'password']
128
        return field_name[0]
129
    except (IndexError,):
130
        return None
131

    
132

    
133
def get_login_info(request, credentials):
134
    """Returns phantomjs login prerequis
135
    """
136
    from mandayejs.applications import get_app_settings
137
    app_settings = get_app_settings()
138
    auth_checker = os.path.join(
139
        settings.STATIC_ROOT, app_settings.SITE_AUTH_CHECKER)
140
    return {
141
        'address': request.build_absolute_uri(app_settings.SITE_LOGIN_PATH),
142
        'cookies': [],
143
        'locators': [credentials.to_login_info()],
144
        'auth_checker': auth_checker,
145
        'form_submit_element': app_settings.SITE_FORM_SUBMIT_ELEMENT
146
    }
147

    
148

    
149
def get_idp():
150
    """Return idp
151
    """
152
    return settings.MELLON_IDENTITY_PROVIDERS[0]['METADATA_URL']
(6-6/7)