Projet

Général

Profil

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

mandayejs / mandayejs / mandaye / utils.py @ 83c9a56a

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

    
17
import os
18
import re
19
import json
20
import subprocess
21
import logging
22
import multiprocessing
23

    
24
from django.conf import settings
25
from django.http import SimpleCookie
26
from django.shortcuts import resolve_url
27
from django.utils.six.moves.urllib import parse as urlparse
28

    
29

    
30

    
31
logger = logging.getLogger(__name__)
32

    
33

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

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

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

    
61
    send_end.send(result)
62
    send_end.close()
63

    
64

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

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

    
81
    return result
82

    
83

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

    
91
    return cookie
92

    
93

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

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

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

    
119
    return data
120

    
121

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

    
134

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

    
150

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