canaille-globuzma/tests/conftest.py

329 lines
9.5 KiB
Python
Raw Normal View History

2020-08-18 15:39:34 +00:00
import datetime
import ldap.ldapobject
import os
import pytest
import slapdtest
2020-08-28 14:07:39 +00:00
from cryptography.hazmat.primitives import serialization as crypto_serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.backends import default_backend as crypto_default_backend
2020-08-19 08:28:28 +00:00
from flask_webtest import TestApp
2020-08-18 15:39:34 +00:00
from werkzeug.security import gen_salt
2020-10-21 12:04:40 +00:00
from canaille import create_app
from canaille.models import User, Client, Token, AuthorizationCode, Consent
from canaille.ldaputils import LDAPObject
2020-08-18 15:39:34 +00:00
class CustomSlapdObject(slapdtest.SlapdObject):
custom_schema_files = ("oauth2-openldap.schema",)
2020-10-20 07:55:05 +00:00
openldap_schema_files = (
"core.schema",
"cosine.schema",
"nis.schema",
"inetorgperson.schema",
)
2020-08-18 15:39:34 +00:00
def _ln_schema_files(self, *args, **kwargs):
dir_path = os.path.join(
os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "schemas"
)
super()._ln_schema_files(*args, **kwargs)
super()._ln_schema_files(self.custom_schema_files, dir_path)
def gen_config(self):
previous = self.openldap_schema_files
self.openldap_schema_files += self.custom_schema_files
config = super().gen_config()
self.openldap_schema_files = previous
return config
2020-08-28 14:07:39 +00:00
@pytest.fixture(scope="session")
def keypair():
key = rsa.generate_private_key(
backend=crypto_default_backend(), public_exponent=65537, key_size=2048
)
private_key = key.private_bytes(
crypto_serialization.Encoding.PEM,
crypto_serialization.PrivateFormat.PKCS8,
crypto_serialization.NoEncryption(),
)
public_key = key.public_key().public_bytes(
crypto_serialization.Encoding.OpenSSH, crypto_serialization.PublicFormat.OpenSSH
)
return private_key, public_key
@pytest.fixture
def keypair_path(keypair, tmp_path):
private_key, public_key = keypair
private_key_path = os.path.join(tmp_path, "private.pem")
with open(private_key_path, "wb") as fd:
fd.write(private_key)
public_key_path = os.path.join(tmp_path, "public.pem")
with open(public_key_path, "wb") as fd:
fd.write(public_key)
return private_key_path, public_key_path
2020-08-18 15:39:34 +00:00
@pytest.fixture(scope="session")
def slapd_server():
slapd = CustomSlapdObject()
try:
slapd.start()
suffix_dc = slapd.suffix.split(",")[0][3:]
slapd.ldapadd(
"\n".join(
[
"dn: " + slapd.suffix,
"objectClass: dcObject",
"objectClass: organization",
"dc: " + suffix_dc,
"o: " + suffix_dc,
"",
"dn: " + slapd.root_dn,
"objectClass: applicationProcess",
"cn: " + slapd.root_cn,
2020-09-28 07:47:00 +00:00
"",
"dn: ou=users," + slapd.suffix,
"objectClass: organizationalUnit",
"ou: users",
2020-08-18 15:39:34 +00:00
]
)
+ "\n"
)
LDAPObject.root_dn = slapd.suffix
2020-09-01 15:11:30 +00:00
User.base = "ou=users"
2020-08-19 08:28:28 +00:00
2020-08-18 15:39:34 +00:00
yield slapd
finally:
slapd.stop()
@pytest.fixture
def slapd_connection(slapd_server):
conn = ldap.ldapobject.SimpleLDAPObject(slapd_server.ldap_uri)
conn.protocol_version = 3
conn.simple_bind_s(slapd_server.root_dn, slapd_server.root_pw)
yield conn
conn.unbind_s()
@pytest.fixture
2020-08-28 14:07:39 +00:00
def app(slapd_server, keypair_path):
2020-08-19 07:09:22 +00:00
os.environ["AUTHLIB_INSECURE_TRANSPORT"] = "true"
2020-08-28 14:07:39 +00:00
private_key_path, public_key_path = keypair_path
2020-08-19 07:09:22 +00:00
2020-08-18 15:39:34 +00:00
app = create_app(
{
2020-08-19 08:28:28 +00:00
"SECRET_KEY": gen_salt(24),
2020-10-21 12:04:40 +00:00
"OAUTH2_METADATA_FILE": "canaille/conf/oauth-authorization-server.sample.json",
"OIDC_METADATA_FILE": "canaille/conf/openid-configuration.sample.json",
2020-08-18 15:39:34 +00:00
"LDAP": {
2020-08-19 07:09:22 +00:00
"ROOT_DN": slapd_server.suffix,
2020-08-18 15:39:34 +00:00
"URI": slapd_server.ldap_uri,
"BIND_DN": slapd_server.root_dn,
"BIND_PW": slapd_server.root_pw,
2020-09-01 15:11:30 +00:00
"USER_BASE": "ou=users",
2020-08-20 08:45:33 +00:00
"USER_FILTER": "(|(uid={login})(cn={login}))",
2020-11-01 10:33:56 +00:00
"USER_CLASS": "inetOrgPerson",
"ADMIN_FILTER": "(|(uid=admin)(sn=admin))",
2020-11-02 11:13:03 +00:00
"USER_ADMIN_FILTER": "(|(uid=moderator)(sn=moderator))",
2020-08-19 08:28:28 +00:00
},
2020-08-24 08:03:48 +00:00
"JWT": {
2020-08-28 14:07:39 +00:00
"PUBLIC_KEY": public_key_path,
"PRIVATE_KEY": private_key_path,
"ALG": "RS256",
"KTY": "RSA",
2020-08-24 08:03:48 +00:00
"EXP": 3600,
"MAPPING": {
"SUB": "uid",
"NAME": "cn",
"PHONE_NUMBER": "telephoneNumber",
2020-10-20 07:55:05 +00:00
"EMAIL": "mail",
"GIVEN_NAME": "givenName",
"FAMILY_NAME": "sn",
"PREFERRED_USERNAME": "displayName",
"LOCALE": "preferredLanguage",
"PICTURE": "photo",
2020-08-24 08:03:48 +00:00
},
},
2020-10-22 15:37:01 +00:00
"SMTP": {
"HOST": "localhost",
"PORT": 25,
2020-10-30 22:55:11 +00:00
"TLS": True,
2020-10-22 15:37:01 +00:00
"LOGIN": "smtp_login",
"PASSWORD": "smtp_password",
"FROM_ADDR": "admin@mydomain.tld",
},
2020-08-18 15:39:34 +00:00
}
)
return app
2020-08-19 07:09:22 +00:00
@pytest.fixture
def testclient(app):
app.config["TESTING"] = True
2020-08-19 08:28:28 +00:00
return TestApp(app)
2020-08-19 07:09:22 +00:00
2020-08-18 15:39:34 +00:00
@pytest.fixture
def client(app, slapd_connection):
2020-09-28 07:47:00 +00:00
Client.ocs_by_name(slapd_connection)
2020-08-18 15:39:34 +00:00
c = Client(
oauthClientID=gen_salt(24),
oauthClientName="Some client",
oauthClientContact="contact@mydomain.tld",
oauthClientURI="https://mydomain.tld",
oauthRedirectURIs=[
"https://mydomain.tld/redirect1",
"https://mydomain.tld/redirect2",
],
oauthLogoURI="https://mydomain.tld/logo.png",
oauthIssueDate=datetime.datetime.now().strftime("%Y%m%d%H%S%MZ"),
oauthClientSecret=gen_salt(48),
2020-08-24 08:52:21 +00:00
oauthGrantType=[
"password",
"authorization_code",
"implicit",
"hybrid",
"refresh_token",
],
2020-08-20 12:30:42 +00:00
oauthResponseType=["code", "token", "id_token"],
2020-08-18 15:39:34 +00:00
oauthScope=["openid", "profile"],
oauthTermsOfServiceURI="https://mydomain.tld/tos",
oauthPolicyURI="https://mydomain.tld/policy",
oauthJWKURI="https://mydomain.tld/jwk",
oauthTokenEndpointAuthMethod="client_secret_basic",
)
c.save(slapd_connection)
2020-08-19 08:28:28 +00:00
2020-08-18 15:39:34 +00:00
return c
2020-08-26 14:27:08 +00:00
@pytest.fixture
def authorization(app, slapd_connection, user, client):
2020-09-28 07:47:00 +00:00
AuthorizationCode.ocs_by_name(slapd_connection)
2020-08-26 14:27:08 +00:00
a = AuthorizationCode(
oauthCode="my-code",
oauthClient=client.dn,
2020-09-07 09:28:29 +00:00
oauthSubject=user.dn,
2020-08-26 14:27:08 +00:00
oauthRedirectURI="https://foo.bar/callback",
oauthResponseType="code",
oauthScope="openid profile",
oauthNonce="nonce",
oauthAuthorizationDate="20200101000000Z",
oauthAuthorizationLifetime="3600",
oauthCodeChallenge="challenge",
oauthCodeChallengeMethod="method",
2020-09-17 09:10:12 +00:00
oauthRevokation="",
2020-08-26 14:27:08 +00:00
)
a.save(slapd_connection)
return a
2020-08-18 15:39:34 +00:00
@pytest.fixture
def user(app, slapd_connection):
2020-09-28 07:47:00 +00:00
User.ocs_by_name(slapd_connection)
2020-08-20 08:45:33 +00:00
u = User(
2020-10-20 09:36:58 +00:00
objectClass=["inetOrgPerson"],
2020-08-20 08:45:33 +00:00
cn="John Doe",
sn="Doe",
uid="user",
2020-10-21 07:52:02 +00:00
mail="john@doe.com",
2020-10-22 15:37:01 +00:00
userPassword="{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz",
2020-08-20 08:45:33 +00:00
)
2020-08-18 15:39:34 +00:00
u.save(slapd_connection)
return u
2020-08-23 17:56:37 +00:00
2020-08-26 13:37:15 +00:00
@pytest.fixture
def admin(app, slapd_connection):
2020-09-28 07:47:00 +00:00
User.ocs_by_name(slapd_connection)
2020-08-26 13:37:15 +00:00
u = User(
2020-10-20 09:36:58 +00:00
objectClass=["inetOrgPerson"],
2020-08-26 13:37:15 +00:00
cn="Jane Doe",
sn="Doe",
uid="admin",
2020-10-21 07:52:02 +00:00
mail="jane@doe.com",
2020-10-22 15:37:01 +00:00
userPassword="{SSHA}Vmgh2jkD0idX3eZHf8RzGos31oerjGiU",
2020-08-26 13:37:15 +00:00
)
u.save(slapd_connection)
return u
2020-11-02 11:13:03 +00:00
@pytest.fixture
def moderator(app, slapd_connection):
User.ocs_by_name(slapd_connection)
u = User(
objectClass=["inetOrgPerson"],
cn="Jack Doe",
sn="Doe",
uid="moderator",
mail="jack@doe.com",
userPassword="{SSHA}+eHyxWqajMHsOWnhONC2vbtfNZzKTkag",
)
u.save(slapd_connection)
return u
2020-08-24 12:44:32 +00:00
@pytest.fixture
def token(slapd_connection, client, user):
2020-09-28 07:47:00 +00:00
Token.ocs_by_name(slapd_connection)
2020-08-24 12:44:32 +00:00
t = Token(
oauthAccessToken=gen_salt(48),
oauthClient=client.dn,
2020-08-24 12:44:32 +00:00
oauthSubject=user.dn,
oauthTokenType=None,
oauthRefreshToken=gen_salt(48),
oauthScope="openid profile",
oauthIssueDate=datetime.datetime.now().strftime("%Y%m%d%H%M%SZ"),
oauthTokenLifetime=str(3600),
)
t.save(slapd_connection)
return t
2020-09-17 10:01:21 +00:00
@pytest.fixture
def consent(slapd_connection, client, user):
2020-09-28 07:47:00 +00:00
Consent.ocs_by_name(slapd_connection)
2020-09-17 10:01:21 +00:00
t = Consent(
oauthClient=client.dn,
oauthSubject=user.dn,
oauthScope=["openid", "profile"],
oauthIssueDate=datetime.datetime.now().strftime("%Y%m%d%H%M%SZ"),
)
t.save(slapd_connection)
return t
2020-08-23 17:56:37 +00:00
@pytest.fixture
def logged_user(user, testclient):
with testclient.session_transaction() as sess:
sess["user_dn"] = user.dn
return user
2020-08-26 13:37:15 +00:00
@pytest.fixture
def logged_admin(admin, testclient):
with testclient.session_transaction() as sess:
sess["user_dn"] = admin.dn
return admin
2020-09-17 08:00:39 +00:00
2020-11-02 11:13:03 +00:00
@pytest.fixture
def logged_moderator(moderator, testclient):
with testclient.session_transaction() as sess:
sess["user_dn"] = moderator.dn
return moderator
2020-09-17 08:00:39 +00:00
@pytest.fixture(autouse=True)
def cleanups(slapd_connection):
yield
for consent in Consent.filter(conn=slapd_connection):
consent.delete(conn=slapd_connection)