4 changed files with 291 additions and 0 deletions
@ -0,0 +1,58 @@
@@ -0,0 +1,58 @@
|
||||
import http from "k6/http"; |
||||
import { check, fail } from "k6"; |
||||
import { authenticate } from "./helpers/auth.js"; |
||||
|
||||
const IDENTITY_URL = __ENV.IDENTITY_URL; |
||||
const API_URL = __ENV.API_URL; |
||||
const CLIENT_ID = __ENV.CLIENT_ID; |
||||
const AUTH_USERNAME = __ENV.AUTH_USER_EMAIL; |
||||
const AUTH_PASSWORD = __ENV.AUTH_USER_PASSWORD_HASH; |
||||
|
||||
export const options = { |
||||
ext: { |
||||
loadimpact: { |
||||
projectID: 3639465, |
||||
name: "Config", |
||||
}, |
||||
}, |
||||
stages: [ |
||||
{ duration: "30s", target: 10 }, |
||||
{ duration: "1m", target: 20 }, |
||||
{ duration: "2m", target: 25 }, |
||||
{ duration: "30s", target: 0 }, |
||||
], |
||||
thresholds: { |
||||
http_req_failed: ["rate<0.01"], |
||||
http_req_duration: ["p(95)<1000"], |
||||
}, |
||||
}; |
||||
|
||||
export function setup() { |
||||
return authenticate(IDENTITY_URL, CLIENT_ID, AUTH_USERNAME, AUTH_PASSWORD); |
||||
} |
||||
|
||||
export default function (data) { |
||||
const params = { |
||||
headers: { |
||||
Accept: "application/json", |
||||
Authorization: `Bearer ${data.access_token}`, |
||||
"X-ClientId": CLIENT_ID, |
||||
}, |
||||
tags: { name: "Config" }, |
||||
}; |
||||
|
||||
const res = http.get(`${API_URL}/config`, params); |
||||
if ( |
||||
!check(res, { |
||||
"config status is 200": (r) => r.status === 200, |
||||
}) |
||||
) { |
||||
fail("config status code was *not* 200"); |
||||
} |
||||
|
||||
const json = res.json(); |
||||
|
||||
check(json, { |
||||
"config version is available": (j) => j.version !== "", |
||||
}); |
||||
} |
||||
@ -0,0 +1,131 @@
@@ -0,0 +1,131 @@
|
||||
import http from "k6/http"; |
||||
import { check, fail } from "k6"; |
||||
import { authenticate } from "./helpers/auth.js"; |
||||
import { uuidv4 } from "https://jslib.k6.io/k6-utils/1.4.0/index.js"; |
||||
|
||||
const IDENTITY_URL = __ENV.IDENTITY_URL; |
||||
const API_URL = __ENV.API_URL; |
||||
const CLIENT_ID = __ENV.CLIENT_ID; |
||||
const AUTH_CLIENT_ID = __ENV.AUTH_CLIENT_ID; |
||||
const AUTH_CLIENT_SECRET = __ENV.AUTH_CLIENT_SECRET; |
||||
|
||||
export const options = { |
||||
ext: { |
||||
loadimpact: { |
||||
projectID: 3639465, |
||||
name: "Groups", |
||||
}, |
||||
}, |
||||
stages: [ |
||||
{ duration: "30s", target: 10 }, |
||||
{ duration: "1m", target: 20 }, |
||||
{ duration: "2m", target: 25 }, |
||||
{ duration: "30s", target: 0 }, |
||||
], |
||||
thresholds: { |
||||
http_req_failed: ["rate<0.01"], |
||||
http_req_duration: ["p(95)<1500"], |
||||
}, |
||||
}; |
||||
|
||||
export function setup() { |
||||
return authenticate( |
||||
IDENTITY_URL, |
||||
CLIENT_ID, |
||||
null, |
||||
null, |
||||
AUTH_CLIENT_ID, |
||||
AUTH_CLIENT_SECRET |
||||
); |
||||
} |
||||
|
||||
export default function (data) { |
||||
const params = { |
||||
headers: { |
||||
Accept: "application/json", |
||||
"Content-Type": "application/json", |
||||
Authorization: `Bearer ${data.access_token}`, |
||||
"X-ClientId": CLIENT_ID, |
||||
}, |
||||
tags: { name: "Groups" }, |
||||
}; |
||||
|
||||
let name = `Name ${uuidv4()}`; |
||||
const createPayload = { |
||||
name: name, |
||||
accessAll: true, |
||||
externalId: `External ${uuidv4()}`, |
||||
}; |
||||
|
||||
const createRes = http.post( |
||||
`${API_URL}/public/groups`, |
||||
JSON.stringify(createPayload), |
||||
params |
||||
); |
||||
if ( |
||||
!check(createRes, { |
||||
"group create status is 200": (r) => r.status === 200, |
||||
}) |
||||
) { |
||||
fail("group create status code was *not* 200"); |
||||
} |
||||
|
||||
const createJson = createRes.json(); |
||||
|
||||
if ( |
||||
!check(createJson, { |
||||
"group create id is available": (j) => j.id !== "", |
||||
}) |
||||
) { |
||||
fail("group create id was *not* available"); |
||||
} |
||||
|
||||
const id = createJson.id; |
||||
const getRes = http.get(`${API_URL}/public/groups/${id}`, params); |
||||
if ( |
||||
!check(getRes, { |
||||
"group get status is 200": (r) => r.status === 200, |
||||
}) |
||||
) { |
||||
fail("group get status code was *not* 200"); |
||||
} |
||||
|
||||
const getJson = getRes.json(); |
||||
|
||||
if ( |
||||
!check(getJson, { |
||||
"group get name matches": (j) => j.name === name, |
||||
}) |
||||
) { |
||||
fail("group get name did *not* match"); |
||||
} |
||||
|
||||
name = `Name ${uuidv4()}`; |
||||
const updatePayload = { |
||||
name: name, |
||||
accessAll: createPayload.accessAll, |
||||
externalId: createPayload.externalId, |
||||
}; |
||||
|
||||
const updateRes = http.put( |
||||
`${API_URL}/public/groups/${id}`, |
||||
JSON.stringify(updatePayload), |
||||
params |
||||
); |
||||
if ( |
||||
!check(updateRes, { |
||||
"group update status is 200": (r) => r.status === 200, |
||||
}) |
||||
) { |
||||
fail("group update status code was *not* 200"); |
||||
} |
||||
|
||||
const deleteRes = http.del(`${API_URL}/public/groups/${id}`, null, params); |
||||
if ( |
||||
!check(deleteRes, { |
||||
"group delete status is 200": (r) => r.status === 200, |
||||
}) |
||||
) { |
||||
fail("group delete status code was *not* 200"); |
||||
} |
||||
} |
||||
@ -0,0 +1,73 @@
@@ -0,0 +1,73 @@
|
||||
import http from "k6/http"; |
||||
import { check, fail } from "k6"; |
||||
import encoding from "k6/encoding"; |
||||
|
||||
/** |
||||
* Authenticate using OAuth against Bitwarden |
||||
* @function |
||||
* @param {string} identityUrl - Identity Server URL |
||||
* @param {string} clientHeader - X-ClientId header value |
||||
* @param {string} username - User email (password grant) |
||||
* @param {string} password - User password (password grant) |
||||
* @param {string} clientId - Client ID (client credentials grant) |
||||
* @param {string} clientSecret - Client secret (client credentials grant) |
||||
*/ |
||||
export function authenticate( |
||||
identityUrl, |
||||
clientHeader, |
||||
username, |
||||
password, |
||||
clientId, |
||||
clientSecret |
||||
) { |
||||
const url = `${identityUrl}/connect/token`; |
||||
const params = { |
||||
headers: { |
||||
Accept: "application/json", |
||||
"X-ClientId": clientHeader, |
||||
}, |
||||
tags: { name: "Login" }, |
||||
}; |
||||
const payload = { |
||||
deviceIdentifier: "a455f262-3d24-4bcd-b178-39dcd67d5c3f", |
||||
}; |
||||
|
||||
if (username !== null) { |
||||
payload["scope"] = "api offline_access"; |
||||
payload["grant_type"] = "password"; |
||||
payload["client_id"] = "web"; |
||||
payload["deviceType"] = "9"; |
||||
payload["deviceName"] = "chrome"; |
||||
payload["username"] = username; |
||||
payload["password"] = password; |
||||
|
||||
params.headers["Auth-Email"] = encoding.b64encode(username); |
||||
} else { |
||||
payload["scope"] = "api.organization"; |
||||
payload["grant_type"] = "client_credentials"; |
||||
payload["client_id"] = clientId; |
||||
payload["client_secret"] = clientSecret; |
||||
} |
||||
|
||||
const res = http.post(url, payload, params); |
||||
|
||||
if ( |
||||
!check(res, { |
||||
"login status is 200": (r) => r.status === 200, |
||||
}) |
||||
) { |
||||
fail("login status code was *not* 200"); |
||||
} |
||||
|
||||
const json = res.json(); |
||||
|
||||
if ( |
||||
!check(json, { |
||||
"login access token is available": (j) => j.access_token !== "", |
||||
}) |
||||
) { |
||||
fail("login access token was *not* available"); |
||||
} |
||||
|
||||
return json; |
||||
} |
||||
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
import { authenticate } from "./helpers/auth.js"; |
||||
|
||||
const IDENTITY_URL = __ENV.IDENTITY_URL; |
||||
const CLIENT_ID = __ENV.CLIENT_ID; |
||||
const AUTH_USERNAME = __ENV.AUTH_USER_EMAIL; |
||||
const AUTH_PASSWORD = __ENV.AUTH_USER_PASSWORD_HASH; |
||||
|
||||
export const options = { |
||||
ext: { |
||||
loadimpact: { |
||||
projectID: 3639465, |
||||
name: "Login", |
||||
}, |
||||
}, |
||||
stages: [ |
||||
{ duration: "30s", target: 10 }, |
||||
{ duration: "1m", target: 20 }, |
||||
{ duration: "2m", target: 25 }, |
||||
{ duration: "30s", target: 0 }, |
||||
], |
||||
thresholds: { |
||||
http_req_failed: ["rate<0.01"], |
||||
http_req_duration: ["p(95)<3000"], |
||||
}, |
||||
}; |
||||
|
||||
export default function (data) { |
||||
authenticate(IDENTITY_URL, CLIENT_ID, AUTH_USERNAME, AUTH_PASSWORD); |
||||
} |
||||
Loading…
Reference in new issue