From 8b4583a157240787d5c0c2edda706e0fb19ec3d6 Mon Sep 17 00:00:00 2001 From: Nicolas MASSE Date: Wed, 27 Jan 2021 11:29:18 +0100 Subject: [PATCH] move keycloakLogin to js lib --- lib/keycloak.js | 99 ++++++++++++++++++++++++++++++++++++++++++++++++- login.js | 66 ++++----------------------------- 2 files changed, 104 insertions(+), 61 deletions(-) diff --git a/lib/keycloak.js b/lib/keycloak.js index ef6c772..b7a68ae 100644 --- a/lib/keycloak.js +++ b/lib/keycloak.js @@ -1,4 +1,6 @@ import { Rate } from "k6/metrics"; +import { uuidv4 } from "https://jslib.k6.io/k6-utils/1.0.0/index.js"; +import http from 'k6/http'; export function pickRealm(realmCount) { var realmId = __VU % realmCount; @@ -29,9 +31,9 @@ export function pickUser(realm) { export var script_errors = Rate("script_errors"); export function wrapWithErrorCounting(fn) { - return () => { + return (data) => { try { - fn(); + fn(data); script_errors.add(0); } catch (e) { script_errors.add(1); @@ -51,3 +53,96 @@ export function buildQueryString(data) { return result.join("&"); } + +export function keycloakEndpoints(keycloakUrl, realmId) { + const BASE_URL = `${keycloakUrl}/realms/${realmId}`; + return { + "login": `${BASE_URL}/protocol/openid-connect/auth`, + "token": `${BASE_URL}/protocol/openid-connect/token`, + "userinfo": `${BASE_URL}/protocol/openid-connect/userinfo`, + } +} + +export function keycloakLogin(endpoints, client, user, check) { + const UI_HEADERS = { + "Accept": "text/html,application/xhtml+xml,application/xml", + "Accept-Encoding": "gzip, deflate", + "Accept-Language": "en-US,en;q=0.5", + "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0", + }; + + const LOGIN_PARAMS = { + "login": "true", + "response_type": "code", + "scope": "openid", + }; + + let login_params = Object.assign(LOGIN_PARAMS, { "client_id": client.clientId, "state": uuidv4(), "redirect_uri": client.redirectUris[0] }); + let query_string = buildQueryString(login_params); + let login_page = http.get(`${endpoints.login}?${query_string}`, { "headers": UI_HEADERS, "tags": { name: "get-login-page" } }); + check(login_page, { + 'login_page.status == 200': (http) => http.status === 200, + }); + + if (login_page.status !== 200) { + throw new Error(`login_page.status is ${login_page.status}, expected 200`); + } + + let authorization_response = login_page.submitForm({ + formSelector: '#kc-form-login', + fields: { username: user.username, password: user.credentials[0].value }, + params: { redirects: 0, "tags": { name: "authorization-request" } }, + }); + + check(authorization_response, { + 'authorization_response.status == 302': (http) => http.status === 302, + }); + + if (authorization_response.status !== 302) { + throw new Error(`authorization_response.status is ${authorization_response.status}, expected 302`); + } + + let location = authorization_response.headers["Location"]; + let re = /[&?]code=([^&]+)(&|$)/; + let matches = [... location.matchAll(re) ]; + let code = matches[0][1]; + + let access_token_request = { + "grant_type": "authorization_code", + "code": code, + "redirect_uri": client.redirectUris[0], + "client_id": client.clientId, + "client_secret": client.secret + }; + let access_token_response = http.post(`${endpoints.token}`, access_token_request, { "tags": { name: "access-token-request" } }); + + check(access_token_response, { + 'access_token_response.status == 200': (http) => http.status === 200, + }); + + if (access_token_response.status !== 200) { + throw new Error(`access_token_response.status is ${access_token_response.status}, expected 200`); + } + + return access_token_response.json(); +} + +export function keycloakRefreshTokens(endpoints, tokens, client, check) { + let access_token_request = { + "grant_type": "refresh_token", + "refresh_token": tokens.refresh_token, + "client_id": client.clientId, + "client_secret": client.secret + }; + let access_token_response = http.post(`${endpoints.token}`, access_token_request, { "tags": { name: "refresh-tokens" } }); + + check(access_token_response, { + 'access_token_response.status == 200': (http) => http.status === 200, + }); + + if (access_token_response.status !== 200) { + throw new Error(`access_token_response.status is ${access_token_response.status}, expected 200`); + } + + return access_token_response.json(); +} \ No newline at end of file diff --git a/login.js b/login.js index 63eeb6d..9f078f6 100644 --- a/login.js +++ b/login.js @@ -1,7 +1,6 @@ import http from 'k6/http'; import { check, group, sleep } from 'k6'; -import { uuidv4 } from "https://jslib.k6.io/k6-utils/1.0.0/index.js"; -import { pickRealm, pickClient, pickUser, wrapWithErrorCounting, buildQueryString } from "./lib/keycloak.js"; +import { pickRealm, pickClient, pickUser, wrapWithErrorCounting, keycloakLogin, keycloakEndpoints } from "./lib/keycloak.js"; import { randomSeed } from 'k6'; export let options = { @@ -12,70 +11,19 @@ export let options = { noVUConnectionReuse: true, }; +randomSeed(__VU); + const realmCount = 10; const realm = pickRealm(realmCount); const realmId = realm.id; -randomSeed(__VU); - -const BASE_URL = `http://hp-microserver.itix.fr/auth/realms/${realmId}`; -const LOGIN_ENDPOINT = `${BASE_URL}/protocol/openid-connect/auth`; -const TOKEN_ENDPOINT = `${BASE_URL}/protocol/openid-connect/token`; -const UI_HEADERS = { - "Accept": "text/html,application/xhtml+xml,application/xml", - "Accept-Encoding": "gzip, deflate", - "Accept-Language": "en-US,en;q=0.5", - "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0", -}; - -const LOGIN_PARAMS = { - "login": "true", - "response_type": "code", -}; +let endpoints = keycloakEndpoints("http://hp-microserver.itix.fr/auth", realmId); function testKCLogin() { - var user = pickUser(realm); - var client = pickClient(realm); - group('login', () => { - let login_params = Object.assign(LOGIN_PARAMS, { "client_id": client.clientId, "state": uuidv4(), "redirect_uri": client.redirectUris[0] }); - let query_string = buildQueryString(login_params); - let login_page = http.get(`${LOGIN_ENDPOINT}?${query_string}`, { "headers": UI_HEADERS, "tags": { name: "get-login-page" } }); - check(login_page, { - 'login_page.status == 200': (http) => http.status === 200, - }); - - if (login_page == null || login_page.status !== 200) { - return; - } - - let authorization_response = login_page.submitForm({ - formSelector: '#kc-form-login', - fields: { username: user.username, password: user.credentials[0].value }, - params: { redirects: 0, "tags": { name: "authorization-request" } }, - }); - - check(authorization_response, { - 'authorization_response.status == 302': (http) => http.status === 302, - }); - - let location = authorization_response.headers["Location"]; - let re = /[&?]code=([^&]+)(&|$)/; - let matches = [... location.matchAll(re) ]; - let code = matches[0][1]; - - let access_token_request = { - "grant_type": "authorization_code", - "code": code, - "redirect_uri": client.redirectUris[0], - "client_id": client.clientId, - "client_secret": client.secret - }; - let access_token_response = http.post(`${TOKEN_ENDPOINT}`, access_token_request, { "tags": { name: "access-token-request" } }); - - check(access_token_response, { - 'access_token_response.status == 200': (http) => http.status === 200, - }); + let user = pickUser(realm); + let client = pickClient(realm); + keycloakLogin(endpoints, client, user, check); }); sleep(2);