LoginSignup
5
1

More than 1 year has passed since last update.

k6でBasic認証とDigest認証のサイトに負荷をかける

Posted at

はじめに

サイトがBasic認証やDigest認証を設定していた場合、どうしたら良いか気になったので調べて試してみました。
ただ実行するだけだとピンとこない部分もあると思うので、curlコマンドのどの実行に相当するのかも併せて記載してます。

事前確認

ますは Basic認証 が設定されているサイトを確認します。
コマンドラインで確認すると以下が確認できます。

401 UNAUTHORIZED
$ curl -i https://httpbin.test.k6.io/basic-auth/user/passwd
HTTP/1.1 401 UNAUTHORIZED
Date: Sun, 11 Sep 2022 06:29:39 GMT
Content-Length: 0
Connection: keep-alive
WWW-Authenticate: Basic realm="Fake Realm"
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
200 OK
$ curl -i --user 'user:passwd' https://httpbin.test.k6.io/basic-auth/user/passwd
HTTP/1.1 200 OK
Date: Sun, 11 Sep 2022 06:40:43 GMT
Content-Type: application/json
Content-Length: 47
Connection: keep-alive
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

{
  "authenticated": true, 
  "user": "user"
}

ブラウザで確認するとこのような感じになります。
スクリーンショット 2022-09-11 15.35.30.png
スクリーンショット 2022-09-11 15.36.29.png

Digest認証のブラウザアクセスは以下です。
スクリーンショット 2022-09-16 21.31.18.png
スクリーンショット 2022-09-16 21.31.32.png

それでは実際に k6 を実行したいと思います。

負荷テスト

Basic認証とDigest認証に対してのBasic認証のサイトには2つの方法でアクセスができます。

方法1. URL埋め込み

認証情報をURLに埋め込む方法です。

basic-auth01.js
import encoding from 'k6/encoding';
import http from 'k6/http';
import { check } from 'k6';

const username = 'user';
const password = 'passwd';

export default function () {
  const credentials = `${username}:${password}`;

  const url = `https://${credentials}@httpbin.test.k6.io/basic-auth/user/passwd`;

  let res = http.get(url);

  // Verify response
  check(res, {
    'status is 200': (r) => r.status === 200,
    'is authenticated': (r) => r.json().authenticated === true,
    'is correct user': (r) => r.json().user === username,
  });
}

IDPASS:で繋げたという組み合わせで curlコマンド に置き換えると以下になります。

curl
$ curl -i  https://user:passwd@httpbin.test.k6.io/basic-auth/user/passwd

それではスクリプトを実行します。

実行
% k6 run basic-auth01.js

          /\      |‾‾| /‾‾/   /‾‾/   
     /\  /  \     |  |/  /   /  /    
    /  \/    \    |     (   /   ‾‾\  
   /          \   |  |\  \ |  ()  | 
  / __________ \  |__| \__\ \_____/ .io

  execution: local
     script: basic-auth01.js
     output: -

  scenarios: (100.00%) 1 scenario, 1 max VUs, 10m30s max duration (incl. graceful stop):
           * default: 1 iterations for each of 1 VUs (maxDuration: 10m0s, gracefulStop: 30s)


running (00m00.8s), 0/1 VUs, 1 complete and 0 interrupted iterations
default ✓ [======================================] 1 VUs  00m00.8s/10m0s  1/1 iters, 1 per VU

     ✓ status is 200
     ✓ is authenticated
     ✓ is correct user

     checks.........................: 100.00% ✓ 3       ✗ 0
     data_received..................: 5.7 kB  7.5 kB/s
     data_sent......................: 515 B   670 B/s
     http_req_blocked...............: avg=579.44ms min=579.44ms med=579.44ms max=579.44ms p(90)=579.44ms p(95)=579.44ms
     http_req_connecting............: avg=183.25ms min=183.25ms med=183.25ms max=183.25ms p(90)=183.25ms p(95)=183.25ms
     http_req_duration..............: avg=185.8ms  min=185.8ms  med=185.8ms  max=185.8ms  p(90)=185.8ms  p(95)=185.8ms 
       { expected_response:true }...: avg=185.8ms  min=185.8ms  med=185.8ms  max=185.8ms  p(90)=185.8ms  p(95)=185.8ms 
     http_req_failed................: 0.00%   ✓ 0       ✗ 1
     http_req_receiving.............: avg=287µs    min=287µs    med=287µs    max=287µs    p(90)=287µs    p(95)=287µs   
     http_req_sending...............: avg=227µs    min=227µs    med=227µs    max=227µs    p(90)=227µs    p(95)=227µs   
     http_req_tls_handshaking.......: avg=198.35ms min=198.35ms med=198.35ms max=198.35ms p(90)=198.35ms p(95)=198.35ms
     http_req_waiting...............: avg=185.29ms min=185.29ms med=185.29ms max=185.29ms p(90)=185.29ms p(95)=185.29ms
     http_reqs......................: 1       1.30138/s
     iteration_duration.............: avg=766.35ms min=766.35ms med=766.35ms max=766.35ms p(90)=766.35ms p(95)=766.35ms
     iterations.....................: 1       1.30138/s

方法2. Authorization ヘッダ指定

Authorization ヘッダを使ったアクセス方法です。

basic-auth02.js
import encoding from 'k6/encoding';
import http from 'k6/http';
import { check } from 'k6';

const username = 'user';
const password = 'passwd';

export default function () {
  const credentials = `${username}:${password}`;

  const encodedCredentials = encoding.b64encode(credentials);
  const options = {
    headers: {
      Authorization: `Basic ${encodedCredentials}`,
    },
  };

  let res = http.get(`https://httpbin.test.k6.io/basic-auth/${username}/${password}`, options);

  check(res, {
    'status is 200': (r) => r.status === 200,
    'is authenticated': (r) => r.json().authenticated === true,
    'is correct user': (r) => r.json().user === username,
  });
}

curlコマンド では以下のようになります。

curl
$ ENC=`echo -n "user:passwd" | base64` | curl -i  https://httpbin.test.k6.io/basic-auth/user/passwd -H "Authorization:Basic ${ENC}"

それではスクリプトを実行します。

実行
% k6 run basic-auth02.js

          /\      |‾‾| /‾‾/   /‾‾/   
     /\  /  \     |  |/  /   /  /    
    /  \/    \    |     (   /   ‾‾\  
   /          \   |  |\  \ |  ()  | 
  / __________ \  |__| \__\ \_____/ .io

  execution: local
     script: basic-auth02.js
     output: -

  scenarios: (100.00%) 1 scenario, 1 max VUs, 10m30s max duration (incl. graceful stop):
           * default: 1 iterations for each of 1 VUs (maxDuration: 10m0s, gracefulStop: 30s)


running (00m01.0s), 0/1 VUs, 1 complete and 0 interrupted iterations
default ✓ [======================================] 1 VUs  00m01.0s/10m0s  1/1 iters, 1 per VU

     ✓ status is 200
     ✓ is authenticated
     ✓ is correct user

     checks.........................: 100.00% ✓ 3        ✗ 0  
     data_received..................: 5.7 kB  5.6 kB/s
     data_sent......................: 515 B   505 B/s
     http_req_blocked...............: avg=828.2ms  min=828.2ms  med=828.2ms  max=828.2ms  p(90)=828.2ms  p(95)=828.2ms 
     http_req_connecting............: avg=181.86ms min=181.86ms med=181.86ms max=181.86ms p(90)=181.86ms p(95)=181.86ms
     http_req_duration..............: avg=185.46ms min=185.46ms med=185.46ms max=185.46ms p(90)=185.46ms p(95)=185.46ms
       { expected_response:true }...: avg=185.46ms min=185.46ms med=185.46ms max=185.46ms p(90)=185.46ms p(95)=185.46ms
     http_req_failed................: 0.00%   ✓ 0        ✗ 1  
     http_req_receiving.............: avg=1.32ms   min=1.32ms   med=1.32ms   max=1.32ms   p(90)=1.32ms   p(95)=1.32ms  
     http_req_sending...............: avg=696µs    min=696µs    med=696µs    max=696µs    p(90)=696µs    p(95)=696µs   
     http_req_tls_handshaking.......: avg=201.94ms min=201.94ms med=201.94ms max=201.94ms p(90)=201.94ms p(95)=201.94ms
     http_req_waiting...............: avg=183.44ms min=183.44ms med=183.44ms max=183.44ms p(90)=183.44ms p(95)=183.44ms
     http_reqs......................: 1       0.981191/s
     iteration_duration.............: avg=1.01s    min=1.01s    med=1.01s    max=1.01s    p(90)=1.01s    p(95)=1.01s   
     iterations.....................: 1       0.981191/s
     vus............................: 1       min=1      max=1
     vus_max........................: 1       min=1      max=1

Digest認証

digest-auth.js
import http from 'k6/http';
import { check } from 'k6';

const username = 'user';
const password = 'passwd';

export default function () {
  const credentials = `${username}:${password}`;
  const res = http.get(
    `https://${credentials}@httpbin.test.k6.io/digest-auth/auth/${username}/${password}`,
    { auth: 'digest' }
  );

  check(res, {
    'status is 200': (r) => r.status === 200,
    'is authenticated': (r) => r.json().authenticated === true,
    'is correct user': (r) => r.json().user === username,
  });
}

curlコマンド では以下のようになります。

curl
$ curl --digest --user "user:passwd" "https://httpbin.test.k6.io/digest-auth/auth/user/passwd"
実行
$ k6 run digest-auth.js                                                                       

          /\      |‾‾| /‾‾/   /‾‾/   
     /\  /  \     |  |/  /   /  /    
    /  \/    \    |     (   /   ‾‾\  
   /          \   |  |\  \ |  ()  | 
  / __________ \  |__| \__\ \_____/ .io

  execution: local
     script: digest-auth.js
     output: -

  scenarios: (100.00%) 1 scenario, 1 max VUs, 10m30s max duration (incl. graceful stop):
           * default: 1 iterations for each of 1 VUs (maxDuration: 10m0s, gracefulStop: 30s)


running (00m00.9s), 0/1 VUs, 1 complete and 0 interrupted iterations
default ✓ [======================================] 1 VUs  00m00.9s/10m0s  1/1 iters, 1 per VU

     ✓ status is 200
     ✓ is authenticated
     ✓ is correct user

     checks.........................: 100.00% ✓ 3        ✗ 0
     data_received..................: 6.3 kB  6.8 kB/s
     data_sent......................: 988 B   1.1 kB/s
     http_req_blocked...............: avg=245.27ms min=5µs      med=245.27ms max=490.55ms p(90)=441.49ms p(95)=466.02ms
     http_req_connecting............: avg=90.66ms  min=0s       med=90.66ms  max=181.33ms p(90)=163.2ms  p(95)=172.27ms
     http_req_duration..............: avg=216.54ms min=201.39ms med=216.54ms max=231.69ms p(90)=228.66ms p(95)=230.17ms
       { expected_response:true }...: avg=216.54ms min=201.39ms med=216.54ms max=231.69ms p(90)=228.66ms p(95)=230.17ms
     http_req_failed................: 0.00%   ✓ 0        ✗ 2
     http_req_receiving.............: avg=164.5µs  min=137µs    med=164.5µs  max=192µs    p(90)=186.5µs  p(95)=189.25µs
     http_req_sending...............: avg=38µs     min=17µs     med=38µs     max=59µs     p(90)=54.8µs   p(95)=56.89µs 
     http_req_tls_handshaking.......: avg=99.22ms  min=0s       med=99.22ms  max=198.45ms p(90)=178.61ms p(95)=188.53ms
     http_req_waiting...............: avg=216.34ms min=201.18ms med=216.34ms max=231.49ms p(90)=228.46ms p(95)=229.98ms
     http_reqs......................: 2       2.157921/s
     iteration_duration.............: avg=924.61ms min=924.61ms med=924.61ms max=924.61ms p(90)=924.61ms p(95)=924.61ms
     iterations.....................: 1       1.07896/s

おわりに

負荷テストを行う際、認証が掛かってる場合は多々あると思います。
一時的に解除することが可能な場合は良いですが、そういうことが難しい場合などにとても有効な手段だと思います。

参考

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1