Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PRs from last week to Grafana docs #1393

Merged
merged 5 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
201 changes: 201 additions & 0 deletions docs/sources/v0.47.x/examples/oauth-authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,207 @@ export function authenticateUsingAzure(tenantId, clientId, clientSecret, scope,

{{< /code >}}

### Azure B2C

The following example shows how you can authenticate with Azure B2C using the [Client Credentials Flow](https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-reference-oauth-code#client-credentials-flow).

This example is based on a JMeter example found at the [azure-ad-b2c/load-tests](https://github.com/azure-ad-b2c/load-tests) repository.

To use this script, you need to:

1. [Set up your own Azure B2C tenant](https://learn.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-tenant)
* Copy the tenant name, it will be used in your test script.
1. [Register a web application](https://learn.microsoft.com/en-us/azure/active-directory-b2c/tutorial-register-applications?tabs=app-reg-ga)
* Register a single page application with the redirect URL of: https://jwt.ms. That's needed for the flow to receive a token.
* After the creation, you can get the Application (client) ID, and the Directory (tenant) ID. Copy both of them, they'll be used in your test script.
1. [Create a user flow so that you can sign up and create a user](https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows)
* Create a new user, and copy the username and password. They'll be used in the test script.

You can find the settings in the B2C settings in the Azure portal if you need to refer to them later on. Make sure to fill out all the variables for the `B2CGraphSettings` object, as well as replace `USERNAME` and `PASSWORD` in `export default function`.

{{< code >}}

```javascript
import http from "k6/http";
import crypto from "k6/crypto";
import { randomString } from "https://jslib.k6.io/k6-utils/1.2.0/index.js";

const B2CGraphSettings = {
B2C: {
client_id: "", // Application ID in Azure
user_flow_name: "",
tenant_id: "", // Directory ID in Azure
tenant_name: "",
scope: "openid",
redirect_url: "https://jwt.ms",
},
};

/**
* Authenticate using OAuth against Azure B2C
* @function
* @param {string} username - Username of the user to authenticate
* @param {string} password
* @return {string} id_token
*/
export function GetB2cIdToken(username, password) {
const state = GetState();
SelfAsserted(state, username, password);
const code = CombinedSigninAndSignup(state);
return GetToken(code, state.codeVerifier);
}

/**
* @typedef {object} b2cStateProperties
* @property {string} csrfToken
* @property {string} stateProperty
* @property {string} codeVerifier
*
*/

/**
* Get the id token from Azure B2C
* @function
* @param {string} code
* @returns {string} id_token
*/
const GetToken = (code, codeVerifier) => {
const url =
`https://${B2CGraphSettings.B2C.tenant_name}.b2clogin.com/${B2CGraphSettings.B2C.tenant_id}` +
`/oauth2/v2.0/token` +
`?p=${B2CGraphSettings.B2C.user_flow_name}` +
`&client_id=${B2CGraphSettings.B2C.client_id}` +
`&grant_type=authorization_code` +
`&scope=${B2CGraphSettings.B2C.scope}` +
`&code=${code}` +
`&redirect_uri=${B2CGraphSettings.B2C.redirect_url}` +
`&code_verifier=${codeVerifier}`;

const response = http.post(url, "", {
tags: {
b2c_login: "GetToken",
},
});

return JSON.parse(response.body).id_token;
};

/**
* Signs in the user using the CombinedSigninAndSignup policy
* extraqct B2C code from response
* @function
* @param {b2cStateProperties} state
* @returns {string} code
*/
const CombinedSigninAndSignup = (state) => {
const url =
`https://${B2CGraphSettings.B2C.tenant_name}.b2clogin.com/${B2CGraphSettings.B2C.tenant_name}.onmicrosoft.com` +
`/${B2CGraphSettings.B2C.user_flow_name}/api/CombinedSigninAndSignup/confirmed` +
`?csrf_token=${state.csrfToken}` +
`&rememberMe=false` +
`&tx=StateProperties=${state.stateProperty}` +
`&p=${B2CGraphSettings.B2C.user_flow_name}`;

const response = http.get(url, "", {
tags: {
b2c_login: "CombinedSigninAndSignup",
},
});
const codeRegex = '.*code=([^"]*)';
return response.url.match(codeRegex)[1];
};

/**
* Signs in the user using the SelfAsserted policy
* @function
* @param {b2cStateProperties} state
* @param {string} username
* @param {string} password
*/
const SelfAsserted = (state, username, password) => {
const url =
`https://${B2CGraphSettings.B2C.tenant_name}.b2clogin.com/${B2CGraphSettings.B2C.tenant_id}` +
`/${B2CGraphSettings.B2C.user_flow_name}/SelfAsserted` +
`?tx=StateProperties=${state.stateProperty}` +
`&p=${B2CGraphSettings.B2C.user_flow_name}` +
`&request_type=RESPONSE` +
`&email=${username}` +
`&password=${password}`;

const params = {
headers: {
"X-CSRF-TOKEN": `${state.csrfToken}`,
},
tags: {
b2c_login: "SelfAsserted",
},
};
http.post(url, "", params);
};

/**
* Calls the B2C login page to get the state property
* @function
* @returns {b2cStateProperties} b2cState
*/
const GetState = () => {
const nonce = randomString(50);
const challenge = crypto.sha256(nonce.toString(), "base64rawurl");

const url =
`https://${B2CGraphSettings.B2C.tenant_name}.b2clogin.com` +
`/${B2CGraphSettings.B2C.tenant_id}/oauth2/v2.0/authorize?` +
`p=${B2CGraphSettings.B2C.user_flow_name}` +
`&client_id=${B2CGraphSettings.B2C.client_id}` +
`&nonce=${nonce}` +
`&redirect_uri=${B2CGraphSettings.B2C.redirect_url}` +
`&scope=${B2CGraphSettings.B2C.scope}` +
`&response_type=code` +
`&prompt=login` +
`&code_challenge_method=S256` +
`&code_challenge=${challenge}` +
`&response_mode=fragment`;

const response = http.get(url, "", {
tags: {
b2c_login: "GetCookyAndState",
},
});

const vuJar = http.cookieJar();
const responseCookies = vuJar.cookiesForURL(response.url);

const b2cState = {};
b2cState.codeVerifier = nonce;
b2cState.csrfToken = responseCookies["x-ms-cpim-csrf"][0];
b2cState.stateProperty = response.body.match('.*StateProperties=([^"]*)')[1];
return b2cState;
};

/**
* Helper function to get the authorization header for a user
* @param {user} user
* @returns {object} httpsOptions
*/
export const GetAuthorizationHeaderForUser = (user) => {
const token = GetB2cIdToken(user.username, user.password);

return {
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + token,
},
};
};

export default function () {
const token = GetB2cIdToken("USERNAME", "PASSWORD");
console.log(token);
}
```

{{< /code >}}

### Okta

{{< code >}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: 'Faults'
excerpt: 'xk6-disruptor: Fault Description'
weight: 01
weight: 100
---

# Faults
Expand All @@ -12,3 +12,4 @@ A fault is as an abnormal condition that affects a system component and which ma
| ------------------------------------------------------------------------------------ | ------------------------------------------- |
| [gRPC Fault](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/xk6-disruptor/faults/grpc) | Fault affecting gRPC requests from a target |
| [HTTP Fault](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/xk6-disruptor/faults/http) | Fault affecting HTTP requests from a target |
| [Pod Termination Fault](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/xk6-disruptor/faults/pod-termination) | Fault terminating a number of target Pods |
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
title: 'Pod Termination'
description: 'xk6-disruptor: Pod Termination Fault attributes'
weight: 03
---

# Pod Termination

A Pod Termination Fault allows terminating either a fixed number or a percentage of the pods that matching a selector or back a service.

A Pod Termination fault is defined by the following attributes:

| Attribute | Type | Description |
| ------------- | ------ | --------|
| count | integer or percentage | the number of pods to be terminated. It can be specified as a integer number or as a percentage, for example `30%`, that defines the fraction of target pods to be terminated|

{{% admonition type="note" %}}

If the count is a percentage and there are no enough elements in the target pod list, the number is rounded up.
For example '25%' of a list of 2 target pods will terminate one pod.
If the list of target pods is not empty, at least one pod is always terminated.

{{% /admonition %}}

## Example

This example defines a PorTermination fault that will terminate `30%` of target pods

```javascript
const fault = {
count: '30%'
};
```
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
title: 'Get started'
excerpt: 'xk6-disruptor is an extension that adds fault injection capabilities to k6. Start here to learn the basics and how to use the disruptor'
weight: 01
weight: 01
---

# Get started
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: 'PodDisruptor'
excerpt: 'xk6-disruptor: PodDisruptor class'
weight: 02
weight: 200
---

# PodDisruptor
Expand All @@ -17,6 +17,7 @@ To construct a `PodDisruptor`, use the [PodDisruptor() constructor](https://graf
| [PodDisruptor.injectGrpcFaults()](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/xk6-disruptor/poddisruptor/injectgrpcfaults) | Inject [gRPC faults](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/xk6-disruptor/faults/grpc) in the target Pods |
| [PodDisruptor.injectHTTPFaults()](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/xk6-disruptor/poddisruptor/injecthttpfaults) | Inject [HTTP faults](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/xk6-disruptor/faults/http) in the target Pods |
| PodDisruptor.targets() | Returns the list of target Pods of the PodDisruptor |
| [PodDisruptor.terminatePods()](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/xk6-disruptor/poddisruptor/terminate-pods) | executes a [Pod Termination fault](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/xk6-disruptor/faults/pod-termination) in the target Pods |

## Example

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
title: 'terminatePods()'
description: 'xk6-disruptor: PodDisruptor.terminatePods method'
---

# terminatePods()

`terminatePods` terminates a number of the pods matching the selector configured in the PodDisruptor.

| Parameter | Type | Description |
| --------- | ------ |------- |
| fault | object | description of the [Pod Termination fault](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/xk6-disruptor/faults/pod-termination) |

## Example

<!-- eslint-skip -->

```javascript
const fault = {
count: 2,
}
disruptor.terminatePods(fault)
```
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: 'ServiceDisruptor'
excerpt: 'xk6-disruptor: ServiceDisruptor class'
weight: 03
weight: 300
---

# ServiceDisruptor
Expand All @@ -16,6 +16,8 @@ To construct a `ServiceDisruptor`, use the [ServiceDisruptor() constructor](http
| ----------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| [ServiceDisruptor.injectGrpcFaults()](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/xk6-disruptor/servicedisruptor/injectgrpcfaults) | Inject [gRPC faults](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/xk6-disruptor/faults/grpc) in the target Pods |
| [ServiceDisruptor.injectHTTPFaults()](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/xk6-disruptor/servicedisruptor/injecthttpfaults) | Inject [HTTTP faults](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/xk6-disruptor/faults/http) in the target Pods |
| ServiceDisruptor.targets() | Returns the list of target Pods of the ServiceDisruptor |
| [ServiceDisruptor.terminatePods()](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/xk6-disruptor/servicedisruptor/terminate-pods) | executes a [Pod Termination fault](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/xk6-disruptor/faults/pod-termination) in the target Pods|

## Example

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
title: 'terminatePods()'
description: 'xk6-disruptor: ServiceDisruptor.terminatePods method'
---

# terminatePods()

`terminatePods` terminates a number of pods that belong to the service specified in the ServiceDisruptor.

| Parameter | Type | Description |
| --------- | ------ |------- |
| fault | object | description of the [Pod Termination fault](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/xk6-disruptor/faults/pod-termination) |

## Example

<!-- eslint-skip -->

```javascript
const fault = {
count: 2,
}
disruptor.terminatePods(fault)
```
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ They determine where k6 displays or saves the content:

The value of a key can have a type of either `string` or [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer).

You can return mutiple summary outputs in a script.
You can return multiple summary outputs in a script.
As an example, this `return` statement sends a report to standard output and writes the `data` object to a JSON file.

{{< code >}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ weight: 01
The `shared-iterations` executor shares iterations between the number of VUs.
The test ends once k6 executes all iterations.

For a shortcut to this executor, use the [vus](https://grafana.com/docs/k6/<K6_VERSION>/using-k6/k6-options/reference#vus) and [iterations](https://grafana.com/docs/k6/<K6_VERSION>/using-k6/k6-options/reference#iterations) options.
For a shortcut to this executor, use the [`vus`](https://grafana.com/docs/k6/<K6_VERSION>/using-k6/k6-options/reference#vus) and [`iterations`](https://grafana.com/docs/k6/<K6_VERSION>/using-k6/k6-options/reference#iterations) options.

{{% admonition type="note" %}}

Expand Down Expand Up @@ -37,7 +37,7 @@ This executor is suitable when you want a specific number of VUs to complete a f
number of total iterations, and the amount of iterations per VU is unimportant.
If the **time to complete** a number of test iterations is your concern, this executor should perform best.

An example use case is for quick performance tests in the developement build cycle.
An example use case is for quick performance tests in the development build cycle.
As developers make changes, they might run the test against the local code to test for performance regressions.
Thus the executor works well with a _shift-left_ policy, where emphasizes testing performance early in the development cycle, when the cost of a fix is lowest.

Expand Down