Projet

Général

Profil

0001-manager-add-a-technical-info-page-with-ldap-configs-.patch

Paul Marillonnet, 01 décembre 2021 17:28

Télécharger (9,92 ko)

Voir les différences:

Subject: [PATCH] manager: add a technical info page with ldap configs (#58938)

 .../static/authentic2/manager/css/style.css   |   9 ++
 .../authentic2/manager/homepage.html          |   3 +
 .../authentic2/manager/ldap_details.html      |  14 +++
 .../authentic2/manager/tech_info.html         |  17 +++
 src/authentic2/manager/urls.py                |   2 +
 src/authentic2/manager/views.py               |  37 +++++++
 tests/test_ldap.py                            | 100 ++++++++++++++++++
 7 files changed, 182 insertions(+)
 create mode 100644 src/authentic2/manager/templates/authentic2/manager/ldap_details.html
 create mode 100644 src/authentic2/manager/templates/authentic2/manager/tech_info.html
src/authentic2/manager/static/authentic2/manager/css/style.css
277 277
a.role-inheritance-view-all {
278 278
    font-style: italic;
279 279
}
280

  
281
div.a2-manager-ldap pre {
282
	background: white;
283
	border: 1px solid black;
284
	padding: .3em;
285
	overflow-x: auto;
286
	white-space: pre-wrap;
287
	word-wrap: break-word;
288
}
src/authentic2/manager/templates/authentic2/manager/homepage.html
17 17
    {% if user.is_superuser or can_view_journal %}
18 18
    <li><a href="{% url 'a2-manager-journal' %}">{% trans 'Journal' %}</a></li>
19 19
    {% endif %}
20
    {% if user.is_superuser %}
21
    <li><a href="{% url 'a2-manager-tech-info' %}">{% trans 'Technical information' %}</a></li>
22
    {% endif %}
20 23
  </ul>
21 24
  </span>
22 25
  {% endif %}
src/authentic2/manager/templates/authentic2/manager/ldap_details.html
1
{% load i18n %}
2
<h4>{% trans "Realm:" %} {{ ldap.realm }}</h4>
3
<div class="a2-manager-ldap-{{ ldap.realm }}">
4
{% if not error %}
5
<h5>{% blocktrans %}Base ldapsearch command:{% endblocktrans %}</h5>
6
 <pre>ldapsearch -v -H {{ ldap.ldap_uri }} -D "{{ ldap.binddn }}" -w "{{ ldap.bindpw }}" -b "{{ ldap.basedn }}"{% if ldap.user_filter or ldap.sync_ldap_users_filter %} "{% firstof ldap.sync_ldap_users_filter ldap.user_filter %}"{% endif %}</pre>
7
{% else %}
8
<div class="error">
9
{% blocktrans %}Error while attempting to connect to LDAP server, base ldapsearch command won't be displayed.{% endblocktrans %}
10
</div>
11
{% endif %}
12
<h5>{% trans "Configuration:" %}</h5>
13
<pre>{{ ldap|pprint }}</pre>
14
</div>
src/authentic2/manager/templates/authentic2/manager/tech_info.html
1
{% extends "authentic2/manager/base.html" %}
2
{% load i18n %}
3

  
4
{% block appbar %}
5
  <h2>{% blocktrans %}{{ title }}{% endblocktrans %}</h2>
6
{% endblock %}
7

  
8
{% block content %}
9
  {% if ldap_list %}
10
  <h3>{% trans "LDAP information" %}</h3>
11
  <div id="a2-manager-tech-info-ldap-list">
12
    {% for ldap in ldap_list %}
13
     {% include "authentic2/manager/ldap_details.html" with ldap=ldap %}
14
    {% endfor %}
15
  </div>
16
{% endif %}
17
{% endblock %}
src/authentic2/manager/urls.py
181 181
        # general management
182 182
        url(r'^site-export/$', views.site_export, name='a2-manager-site-export'),
183 183
        url(r'^site-import/$', views.site_import, name='a2-manager-site-import'),
184
        # technical information including ldap config
185
        url(r'^tech-info/$', views.tech_info, name='a2-manager-tech-info'),
184 186
    ],
185 187
)
186 188

  
src/authentic2/manager/views.py
661 661
homepage = HomepageView.as_view()
662 662

  
663 663

  
664
class TechnicalInformationView(TitleMixin, MediaMixin, TemplateView):
665
    template_name = 'authentic2/manager/tech_info.html'
666
    title = _("Technical information")
667

  
668
    def get(self, request, *args, **kwargs):
669
        if not request.user.is_superuser:
670
            raise PermissionDenied
671
        return super().get(request, *args, **kwargs)
672

  
673
    def get_context_data(self, **kwargs):
674
        import ldap
675

  
676
        from authentic2.backends import ldap_backend
677

  
678
        backend = ldap_backend.LDAPBackend
679
        kwargs['ldap_list'] = []
680
        for block in backend.get_config():
681
            config = block.copy()
682
            conn = backend.get_connection(config)
683
            if not conn:
684
                kwargs['error'] = True
685
            else:
686
                # retrieve ldap uri, not directly visible in configuration block
687
                config['ldap_uri'] = conn.get_option(ldap.OPT_URI)
688
                # user filters need to be formatted to ldapsearch syntax
689
                config['user_filter'] = force_text(block.get('user_filter'), '').replace('%s', '*')
690
                config['sync_ldap_users_filter'] = (
691
                    force_text(block.get('sync_ldap_users_filter'), '').replace('%s', '*').replace('%s', '*')
692
                )
693

  
694
            kwargs['ldap_list'].append(config)
695
        return super().get_context_data(**kwargs)
696

  
697

  
698
tech_info = TechnicalInformationView.as_view()
699

  
700

  
664 701
class MenuJson(HomepageView):
665 702
    def get(self, request, *args, **kwargs):
666 703
        menu_entries = []
tests/test_ldap.py
26 26
from django.contrib.auth import get_user_model
27 27
from django.core import mail, management
28 28
from django.core.exceptions import ImproperlyConfigured
29
from django.urls import reverse
29 30
from django.utils import timezone
30 31
from django.utils.encoding import force_bytes, force_text
31 32
from ldap.dn import escape_dn_chars
......
2108 2109
    )
2109 2110
    user = ldap_backend.LDAPUser.objects.get(username='%s@ldap' % UID)
2110 2111
    utils.assert_event('user.login.failure', user=user, username=UID, reason=exception[1])
2112

  
2113

  
2114
def test_technical_info_ldap(app, admin, superuser, slapd, settings, monkeypatch):
2115
    settings.LDAP_AUTH_SETTINGS = [
2116
        {
2117
            'url': [slapd.ldap_url],
2118
            'binddn': force_text('cn=%s,o=ôrga' % escape_dn_chars('Étienne Michu')),
2119
            'bindpw': 'passé',
2120
            'basedn': 'o=ôrga',
2121
            'use_tls': False,
2122
        }
2123
    ]
2124

  
2125
    utils.login(app, admin, 'a2-manager-homepage')
2126
    app.get(reverse('a2-manager-tech-info'), status=403)
2127
    utils.logout(app)
2128

  
2129
    resp = utils.login(app, superuser, 'a2-manager-tech-info')
2130
    ldap_config_text = resp.pyquery('div#a2-manager-tech-info-ldap-list').text()
2131

  
2132
    assert 'Base ldapsearch command' in ldap_config_text
2133
    assert 'ldapsearch -v -H ldapi://' in ldap_config_text
2134
    assert '-D "cn=Étienne Michu,o=ôrga" -w "passé" -b "o=ôrga" "(|(mail=*)(uid=*))"' in ldap_config_text
2135

  
2136
    for opt in [
2137
        'active_directory',
2138
        'attribute_mappings',
2139
        'attributes',
2140
        'basedn',
2141
        'bind_with_username',
2142
        'binddn',
2143
        'bindpw',
2144
        'bindsasl',
2145
        'cacertdir',
2146
        'cacertfile',
2147
        'can_reset_password',
2148
        'certfile',
2149
        'clean_external_id_on_update',
2150
        'connect_with_user_credentials',
2151
        'create_group',
2152
        'disable_update',
2153
        'email_field',
2154
        'external_id_tuples',
2155
        'extra_attributes',
2156
        'fname_field',
2157
        'global_ldap_options',
2158
        'group_basedn',
2159
        'group_filter',
2160
        'group_mapping',
2161
        'group_to_role_mapping',
2162
        'groupactive',
2163
        'groupstaff',
2164
        'groupsu',
2165
        'is_staff',
2166
        'is_superuser',
2167
        'keep_password',
2168
        'keep_password_in_session',
2169
        'keyfile',
2170
        'ldap_options',
2171
        'ldap_uri',
2172
        'limit_to_realm',
2173
        'lname_field',
2174
        'lookups',
2175
        'mandatory_attributes_values',
2176
        'member_of_attribute',
2177
        'multimatch',
2178
        'ou_slug',
2179
        'ppolicy_dn',
2180
        'realm',
2181
        'referrals',
2182
        'replicas',
2183
        'require_cert',
2184
        'set_mandatory_groups',
2185
        'set_mandatory_roles',
2186
        'shuffle_replicas',
2187
        'sync_ldap_users_filter',
2188
        'timeout',
2189
        'update_username',
2190
        'url',
2191
        'use_controls',
2192
        'use_first_url_for_external_id',
2193
        'use_password_modify',
2194
        'use_tls',
2195
        'user_attributes',
2196
        'user_basedn',
2197
        'user_can_change_password',
2198
        'user_dn_template',
2199
        'user_filter',
2200
        'username_template',
2201
    ]:
2202
        assert opt in ldap_config_text
2203

  
2204
    # mock a buggy connection
2205
    monkeypatch.setattr(ldap_backend.LDAPBackend, 'get_connection', lambda x: None)
2206
    resp = app.get(reverse('a2-manager-tech-info'))
2207
    ldap_config_text = resp.pyquery('div#a2-manager-tech-info-ldap-list').text()
2208

  
2209
    assert 'Base ldapsearch command' not in ldap_config_text
2210
    assert 'Error while attempting to connect to LDAP server' in ldap_config_text
2111
-