provider oauth2 test

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
This commit is contained in:
Marc 'risson' Schmitt
2024-04-11 19:10:47 +02:00
parent 1f4ed1defa
commit 95692f5a7c
3 changed files with 209 additions and 3 deletions

View File

@ -14,7 +14,10 @@ django.setup()
from django.conf import settings from django.conf import settings
from authentik.core.models import Group, User from authentik.core.models import Application, Group, User
from authentik.crypto.models import CertificateKeyPair
from authentik.flows.models import Flow
from authentik.providers.oauth2.models import OAuth2Provider
from authentik.stages.authenticator_static.models import StaticToken from authentik.stages.authenticator_static.models import StaticToken
from authentik.tenants.models import Domain, Tenant from authentik.tenants.models import Domain, Tenant
@ -97,6 +100,43 @@ def login():
) )
def provider_oauth2():
tenants = [
# Number of user policies, group policies, expression policies
(0, 0, 0),
]
for tenant in tenants:
user_policies_count = tenant[0]
group_policies_count = tenant[1]
expression_policies_count = tenant[2]
tenant_name = f"provider-oauth2-{user_policies_count}-{group_policies_count}-{expression_policies_count}"
t = Tenant.objects.create(schema_name=f"t_{tenant_name.replace('-', '_')}", name=uuid4())
Domain.objects.create(tenant=t, domain=f"{tenant_name}.localhost")
with t:
user = User(username="test", name=uuid4())
user.set_password("verySecurePassword")
user.save()
provider = OAuth2Provider.objects.create(
name="test",
authorization_flow=Flow.objects.get(
slug="default-provider-authorization-implicit-consent"
),
signing_key=CertificateKeyPair.objects.get(
name="authentik Self-signed Certificate"
),
redirect_uris="http://test.localhost",
client_id="123456",
client_secret="123456",
)
application = Application.objects.create(slug="test", name="test", provider=provider)
# TODO: create policies
def delete(): def delete():
Tenant.objects.exclude(schema_name="public").delete() Tenant.objects.exclude(schema_name="public").delete()
@ -111,6 +151,7 @@ if __name__ == "__main__":
case "create": case "create":
user_list() user_list()
login() login()
provider_oauth2()
case "delete": case "delete":
delete() delete()
case _: case _:

View File

@ -0,0 +1,165 @@
import crypto from "k6/crypto";
import exec from "k6/execution";
import http from "k6/http";
import { check, fail } from "k6";
const testcases = [[0, 0, 0]];
const VUs = 12;
export const options = {
scenarios: Object.fromEntries(
testcases.map((obj, i) => [
`${obj[0]}_${obj[1]}_${obj[2]}`,
{
executor: "constant-vus",
vus: VUs,
duration: "300s",
startTime: `${315 * i}s`,
env: {
USER_POLICIES_COUNT: `${obj[0]}`,
GROUP_POLICIES_COUNT: `${obj[1]}`,
EXPRESSION_POLICIES_COUNT: `${obj[2]}`,
},
tags: {
testid: `provider-oauth2-${obj[0]}_${obj[1]}_${obj[2]}`,
user_policies_count: `${obj[0]}`,
group_policies_count: `${obj[1]}`,
expression_policies_count: `${obj[2]}`,
},
},
]),
),
};
export function setup() {
let cookies = {};
for (let vu = 1; vu <= VUs; vu++) {
cookies[vu] = {};
for (const testcase of testcases) {
const user_policies_count = testcase[0];
const group_policies_count = testcase[1];
const expression_policies_count = testcase[2];
const domain = `provider-oauth2-${user_policies_count}-${group_policies_count}-${expression_policies_count}.localhost:9000`;
const url = `http://${domain}/api/v3/flows/executor/default-authentication-flow/`;
const params = {
headers: {
"Content-Type": "application/json",
Accept: "*/*",
},
};
http.cookieJar().clear(`http://${domain}`);
let res = http.get(url, params);
let i = 0;
while (true) {
if (i > 10) {
fail("Test made more than 10 queries.");
break;
}
check(res, {
"status is 200": (res) => res.status === 200,
});
if (res.status !== 200) {
fail("Endpoint did not return 200.");
break;
}
const component = res.json()["component"];
let payload = {};
if (component === "ak-stage-identification") {
payload = {
uid_field: "test",
};
} else if (component === "ak-stage-password") {
payload = {
password: "verySecurePassword",
};
} else if (component === "xak-flow-redirect") {
break;
} else {
fail(`Unknown component type: ${component}`);
break;
}
payload["component"] = component;
res = http.post(url, JSON.stringify(payload), params);
i++;
}
cookies[vu][domain] = http
.cookieJar()
.cookiesForURL(`http://${domain}`);
}
}
return { cookies };
}
export default function (data) {
// Restore cookies
let jar = http.cookieJar();
const vu = exec.vu.idInTest;
Object.keys(data.cookies[vu]).forEach((domain) => {
Object.keys(data.cookies[vu][domain]).forEach((key) => {
jar.set(`http://${domain}`, key, data.cookies[vu][domain][key][0]);
});
});
const user_policies_count = Number(__ENV.USER_POLICIES_COUNT);
const group_policies_count = Number(__ENV.GROUP_POLICIES_COUNT);
const expression_policies_count = Number(__ENV.EXPRESSION_POLICIES_COUNT);
const domain = `provider-oauth2-${user_policies_count}-${group_policies_count}-${expression_policies_count}.localhost:9000`;
const params = {
headers: {
"Content-Type": "application/json",
Accept: "*/*",
},
};
const random = (length = 32) => {
let chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let str = "";
for (let i = 0; i < length; i++) {
str += chars.charAt(Math.floor(Math.random() * chars.length));
}
return str;
};
const state = random(32);
const nonce = random(32);
const code_verifier = random(64);
const code_challenge = crypto.sha256(code_verifier, "base64");
const urlParams = {
response_type: "code",
scope: "openid profile email",
client_id: "123456",
redirect_uri: "http://test.localhost",
state: state,
nonce: nonce,
code_challenge: code_challenge,
code_challenge_method: "S256",
};
let url = `http://${domain}/application/o/authorize/?${Object.entries(
urlParams,
)
.map((kv) => kv.map(encodeURIComponent).join("="))
.join("&")}`;
let res = http.get(url, params);
check(res, {
"status is 200": (res) => res.status === 200,
});
if (res.status !== 200) {
fail("Endpoint did not return 200.");
return;
}
url = `http://${domain}/api/v3/flows/executor/default-provider-authorization-implicit-consent/`;
res = http.get(url, params);
check(res, {
"status is 200": (res) => res.status === 200,
"last redirect is present": (res) => res.json()["type"] === "redirect",
});
if (res.status !== 200) {
fail("Endpoint did not return 200.");
return;
}
}

View File

@ -64,14 +64,14 @@ export default function () {
const groups_per_user = Number(__ENV.GROUPS_PER_USER); const groups_per_user = Number(__ENV.GROUPS_PER_USER);
const parents_per_group = Number(__ENV.PARENTS_PER_GROUP); const parents_per_group = Number(__ENV.PARENTS_PER_GROUP);
const with_groups = Number(__ENV.WITH_GROUPS); const with_groups = Number(__ENV.WITH_GROUPS);
const domain = `user-list-${user_count}-${groups_per_user}-${parents_per_group}`; const domain = `user-list-${user_count}-${groups_per_user}-${parents_per_group}.localhost:9000`;
const page_size = Number(__ENV.PAGE_SIZE); const page_size = Number(__ENV.PAGE_SIZE);
const pages = Math.round(user_count / page_size); const pages = Math.round(user_count / page_size);
let requests = []; let requests = [];
for (let page = 1; page <= pages; page++) { for (let page = 1; page <= pages; page++) {
requests.push([ requests.push([
"GET", "GET",
`http://${domain}.localhost:9000/api/v3/core/users/?page=${page}&page_size=${page_size}&include_groups=${with_groups}`, `http://${domain}/api/v3/core/users/?page=${page}&page_size=${page_size}&include_groups=${with_groups}`,
null, null,
{ {
headers: { headers: {