passerelle/tests/ldap/test_manager.py

177 lines
10 KiB
Python

# passerelle - uniform access to multiple data sources and services
# Copyright (C) 2022 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import json
import pytest
from django.core.files.base import ContentFile
from webtest import Upload
pytestmark = pytest.mark.django_db
def login(app, username='admin', password='admin'):
login_page = app.get('/login/')
login_form = login_page.forms[0]
login_form['username'] = username
login_form['password'] = password
resp = login_form.submit()
assert resp.status_int == 302
return app
@pytest.fixture
def app(app, admin_user):
login(app)
return app
def test_add(app, db, cert_content, key_content, resource_class):
response = app.get('/manage/ldap/add')
assert 'this option is actually not supported' in response.text
response.form.set('slug', 'resource')
response.form.set('title', 'resource')
response.form.set('description', 'resource')
response.form.set('ldap_url', 'ldap://localhost.entrouvert.org')
response.form.set('ldap_bind_dn', 'uid=user,o=orga')
response.form.set('ldap_bind_password', 'password')
response.form.set('ldap_tls_cert', Upload('cert.pem', cert_content, 'application/octet-stream'))
response.form.set('ldap_tls_key', Upload('key.pem', key_content, 'application/octet-stream'))
response = response.form.submit(status=302)
assert resource_class.objects.count() == 1
resource = resource_class.objects.get()
assert resource.ldap_url == 'ldap://localhost.entrouvert.org'
assert resource.ldap_bind_dn == 'uid=user,o=orga'
assert resource.ldap_bind_password == 'password'
with resource.ldap_tls_cert as fd:
assert fd.read() == cert_content
with resource.ldap_tls_key as fd:
assert fd.read() == key_content
def test_missing_bind_password(app, db, cert_content, key_content, resource_class):
response = app.get('/manage/ldap/add')
response.form.set('slug', 'resource')
response.form.set('title', 'resource')
response.form.set('description', 'resource')
response.form.set('ldap_url', 'ldap://localhost.entrouvert.org')
response.form.set('ldap_bind_dn', 'uid=user,o=orga')
response = response.form.submit(status=200)
def test_missing_bind_dn(app, db, cert_content, key_content, resource_class):
response = app.get('/manage/ldap/add')
response.form.set('slug', 'resource')
response.form.set('title', 'resource')
response.form.set('description', 'resource')
response.form.set('ldap_url', 'ldap://localhost.entrouvert.org')
response.form.set('ldap_bind_password', 'password')
response = response.form.submit(status=200)
def test_missing_tls_key(app, db, cert_content, key_content, resource_class):
response = app.get('/manage/ldap/add')
response.form.set('slug', 'resource')
response.form.set('title', 'resource')
response.form.set('description', 'resource')
response.form.set('ldap_url', 'ldap://localhost.entrouvert.org')
response.form.set('ldap_tls_cert', Upload('cert.pem', cert_content, 'application/octet-stream'))
response = response.form.submit(status=200)
def test_missing_tls_cert(app, db, cert_content, key_content, resource_class):
response = app.get('/manage/ldap/add')
response.form.set('slug', 'resource')
response.form.set('title', 'resource')
response.form.set('description', 'resource')
response.form.set('ldap_url', 'ldap://localhost.entrouvert.org')
response.form.set('ldap_tls_key', Upload('key.pem', key_content, 'application/octet-stream'))
response = response.form.submit(status=200)
def test_python_ldap_32(app, db):
response = app.get('/manage/ldap/add')
assert 'Warning: this option is actually not supported (python-ldap < 3.4)' in response.text
EXPORT_JSON = {
'resources': [
{
'@type': 'passerelle-resource',
'access_rights': [{'apiuser': 'all', 'codename': 'can_access'}],
'description': 'resource',
'ldap_bind_dn': None,
'ldap_bind_password': None,
'ldap_tls_cert': {
'name': 'cert.pem',
'content': 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCakNDQWU2Z0F3SUJBZ0lVVEtvcFQ3NkNGbHNWY0k3RkFpbGFZTElMejBvd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RWhNQjhHQTFVRUF3d1liRzlqWVd4b2IzTjBMbVZ1ZEhKdmRYWmxjblF1YjNKbk1CNFhEVEU0TVRJdwpOVEUyTlRreU5Gb1hEVEk0TVRJd01qRTJOVGt5TkZvd0l6RWhNQjhHQTFVRUF3d1liRzlqWVd4b2IzTjBMbVZ1CmRISnZkWFpsY25RdWIzSm5NSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTR4c0wKbjI1eWl0dGJqazViY0t2WTJJOHpQaXZMNllXbjJNSmltYVFRU056Q3cvOFBPbVZQTG1NSWIzbGNaanlkRlJhZAorUlR4WmZudXZDQ0pybkdyRzdoT3NKTmVuVExMVTB1Z04veVExODY5Y00wN2E5dGpTekw3TkN6OUgxTklLMStRCmNCc1RFeGM3N2RPV3B3V0k5VGpxWVlSTCt6ZXgzbWw4Y2RxY1E3QlFVUXhBdkE0VVU2M0RNMkcrNU8zZEU3bDgKdXZ5QlVVM2tXL3NoSHloZndlV05YTzhJWFhJanZEZlBZa09zamM2ZW4ya0ZNcitzRU5TVUtnZkRLanovVXpxeQpTN0xCYjR0a0pBTFpNOFFQNTZWZVFBRzFKWkYySjIveTFScUJmSUdSSUVrWW9hSGNqNlVBVFphMXhjWmpNdWJMCnozb3RSTlljUlhLSk1ZV0diUUlEQVFBQm96SXdNREFKQmdOVkhSTUVBakFBTUNNR0ExVWRFUVFjTUJxQ0dHeHYKWTJGc2FHOXpkQzVsYm5SeWIzVjJaWEowTG05eVp6QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFGVlBhdkJhaAptSWpnblRqcTZaYkZ4WFROSlcwVHJxTjhvbGJLSjZTZndXVmswSThweDdQT2VrRmFYZCtlZ3NGSmxXWXlIOXE0CkhrS290ZGRSWVlyV29YY1Bpb2ROZlVhK2JSbmgyV1lsMnJFR01XNWRiQmYvTVlDRHRzNjhjM1NvQTdKSVlKOHcKMFFaR0FraWpLTnRWTUwwL0ZyTHVKV2JmRkJBV0g4SkI0NkJjQWcvOGZsYk1IQVVMelYzRjFnL3YwQTNGRzNZLwo5ZlZyK2xONXFzK05COU5YSU1kZjV3WHJtSlFZUmpvdHlPalVPNnlURnFERnZxRTdERXBLUUQ1aG52cUpvWEN6CnpZUVMxRGpIMXFTUmM1dkM4STdZbEpvd0Nmbkk5TXNFSUNTcnNrNzVEaFQwOTFhSkMyWFg5M280emhmTnhtTzUKS2oyOGhQODdHSGdOSWc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==', # pylint: disable=line-too-long
},
'ldap_tls_key': {
'name': 'key.pem',
'content': 'LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2d0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktrd2dnU2xBZ0VBQW9JQkFRRGpHd3VmYm5LSzIxdU8KVGx0d3E5allqek0rSzh2cGhhZll3bUtacEJCSTNNTEQvdzg2WlU4dVl3aHZlVnhtUEowVkZwMzVGUEZsK2U2OApJSW11Y2FzYnVFNndrMTZkTXN0VFM2QTMvSkRYenIxd3pUdHIyMk5MTXZzMExQMGZVMGdyWDVCd0d4TVRGenZ0CjA1YW5CWWoxT09waGhFdjdON0hlYVh4eDJweERzRkJSREVDOERoUlRyY016WWI3azdkMFR1WHk2L0lGUlRlUmIKK3lFZktGL0I1WTFjN3doZGNpTzhOODlpUTZ5TnpwNmZhUVV5djZ3UTFKUXFCOE1xUFA5VE9ySkxzc0Z2aTJRawpBdGt6eEEvbnBWNUFBYlVsa1hZbmIvTFZHb0Y4Z1pFZ1NSaWhvZHlQcFFCTmxyWEZ4bU15NXN2UGVpMUUxaHhGCmNva3hoWVp0QWdNQkFBRUNnZ0VBT1VaSTJCeHlwckpMbE1nT0o0d3ZVKzVKYmhSOWlKYzhqVjM0bitiUWRJKzQKVHRXMGNYVzdVbWVIYVJXaVIrWmhkMEFNOXhSaERPYkxYb2FXTW5oWVB0VnNndnVua04yT2lhTTQ5T1d0WWIreAo1eERiTzRoSXNsNVpHLzk4bHJuYUtaWWdSeVdNMmZPeUdYaVROZXdmYmppOFkzdUo3Z0ZOeWxtd0dNYVpRamhyCllOYXFORVY3VnMybjdvRVJ4cXpLRzk5NDdvQkF4MmhwbW9hVzZlTXlYY1dsMm92N2lIcEpTS1VCS2hvKzVQV2MKSjczMW5vME9zR3VTKzNqSGEvMG5aWHJUOG5LbWVteURNZFNmV210VHY2NTlML2d1RkluWnBIUGZGVkxmNTZ2YwpKNnpiL0l6RUpWK05oN0NmQnNNYkhsVFlCZVVGbFJXc3k5dDcwK09ad1FLQmdRRDNKNGFWTjR2SmhYWDF6RGdMCmRWQWN6d0xHS1hZMzhCb0JqT2VSdFZoWEhzNXAvZU5JcWVaMlliWXdCQnkzbkw0MTRVbjdncWI5ZkR0ZzBpM24KNW1RSU9XaHZwSVlVeHR3SVBnWXd6dW14eHAvbjdYZFU0QlBEYnhlalp4a3VDN0FSNWJCMzRwd0pBSnZXUkdFZgowWDFUeEpscVVMaGlaNmcxOE8zUzBvaUp0d0tCZ1FEck85Uk9hajZra3hqWUhtbGpCWklYWGhkS0RjbjBBcVBpCncyMEFhYWZ4MG94TlFBb3E4R3R1MjJaMVFId1JkQmVVSndxQ2JtSFZDQ3diTWYvNTY4ekZBQU51VDliS01lNlgKSjBwMG5URGl5bjh3OU1mZHVGdUc0Y1VNbjRvSzZkSXVZbHNjZ3VvUFFDdlFkY2l3RytkanF3VHJIaWI1VEVibQpqZUtFa1kyQSt3S0JnUUR2WHQrd3kyQmVxQnpNRjZNOExiMk9lVXdWZ25pVnlyeFZQaFBWZ2s1eDZrcytTb0FECmsxRzYyLzNvMlVLNjdsc21zZkRHWUE2OXVNR0ZqMnFZakFIY0dVVzF3eUY5SS9CZEp6MDFybUNXSm1vZTVWWEsKNVU4ZTNBeUgzTVY5WENLRjR2Q2IyK1VGcndvL1puQ3VzV1Z4YVJxdzVrYitQNmlodlp1SXNSRStWd0tCZ1FDNwoyZHVCZzNiakZsVVF3YmlIU3p1UFRhUnJqdmRuMVhQcTh3Vm8vdmNQTm9TMGJCK3lpcXhBcXhUM0xiZm1lRDhjCklORlR0N0tJM1MzYnllSVJReTBUWlI5WVNJbk9qbkZxWkFZaGVpWS85bFg4VW40Sm9kLzFwdllsVG9KK2xKczAKVDNkVEhYaXRGU0hvSnlkTSsvdWNyRVlSUE5NQzR0Yjc1dkt0eTA2bFlRS0JnUUN4NDkrZzVrUWFhUlorNHBzdworZW9sTXBBd0tEa3BLNWdZZW42T3NyVDhtNGhweFRtdGl0ZU1zSDVBdmIvZnhxb0pXTE9qaE40RW5FWlRNSnpyCkx5R29Lc1R2N3JoWndoUnpuRTE1ck96eG1sZFdyY0NrbDdER3VNMkdjS2dndWhDWUY3VTdLQSt2VUNlcUNFMEgKTEEyZ3JrWStUeEZwZzFwd1lkRjFoZWttVHc9PQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg==', # pylint: disable=line-too-long
},
'ldap_tls_cacert': None,
'ldap_tls_check_hostname': True,
'ldap_tls_check_cert': True,
'ldap_url': 'ldap://localhost.entrouvert.org:52271',
'log_level': 'INFO',
'resource_type': 'ldap.resource',
'slug': 'resource',
'title': 'resource',
}
],
}
class TestImportExport:
@pytest.fixture
def resource_params(self, resource_params, cert_content, key_content):
return {
**resource_params,
'ldap_url': 'ldap://localhost.entrouvert.org:52271',
'ldap_tls_cert': ContentFile(cert_content, name='cert.pem'),
'ldap_tls_key': ContentFile(key_content, name='key.pem'),
}
def test_import(self, app, resource_class, resource_params):
assert not resource_class.objects.count()
response = app.get('/manage/')
response = response.click('Import')
response.form.set('site_json', Upload('ldap.json', json.dumps(EXPORT_JSON).encode()))
response.form.set('import_users', False)
response = response.form.submit(status=302)
instance = resource_class.objects.get()
for key, value in resource_params.items():
instance_value = getattr(instance, key)
if isinstance(value, ContentFile):
with instance_value as fd1:
with value as fd2:
assert fd1.read() == fd2.read()
else:
assert instance_value == value
def test_export(self, app, resource, cert_content, key_content):
response = app.get('/ldap/resource/')
response = response.click('Export')
content = response.json
for r in content['resources']:
if r.get('ldap_tls_cert'):
r['ldap_tls_cert']['name'] = 'cert.pem'
if r.get('ldap_tls_key'):
r['ldap_tls_key']['name'] = 'key.pem'
assert content == EXPORT_JSON