test_merchant_instance_auth.sh (17600B)
1 #!/usr/bin/env bash 2 # This file is part of TALER 3 # Copyright (C) 2014-2023 Taler Systems SA 4 # 5 # TALER is free software; you can redistribute it and/or modify 6 # it under the terms of the GNU General Public License as 7 # published by the Free Software Foundation; either version 3, or 8 # (at your option) any later version. 9 # 10 # TALER is distributed in the hope that it will be useful, but 11 # WITHOUT ANY WARRANTY; without even the implied warranty of 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 # GNU General Public License for more details. 14 # 15 # You should have received a copy of the GNU General Public 16 # License along with TALER; see the file COPYING. If not, see 17 # <http://www.gnu.org/licenses/> 18 # 19 20 # Cleanup to run whenever we exit 21 function my_cleanup() 22 { 23 for n in $(jobs -p) 24 do 25 kill "$n" 2> /dev/null || true 26 done 27 wait 28 if [ -n "${LAST_RESPONSE+x}" ] 29 then 30 rm -f "${LAST_RESPONSE}" 31 fi 32 } 33 34 . setup.sh 35 36 setup -c test_template.conf -m 37 CONF="test_template.conf.edited" 38 LAST_RESPONSE=$(mktemp -p "${TMPDIR:-/tmp}" test_response.conf-XXXXXX) 39 40 echo -n "Configuring 'admin' instance ..." >&2 41 42 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 43 http://localhost:9966/management/instances \ 44 -d '{"auth":{"method":"token","password":"new_pw"},"id":"admin","name":"default","user_type":"business","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \ 45 -w "%{http_code}" -s -o /dev/null) 46 47 if [ "$STATUS" != "204" ] 48 then 49 exit_fail "Expected 204, instance created. got: $STATUS" >&2 50 fi 51 52 53 BASIC_AUTH=$(echo -n admin:new_pw | base64) 54 55 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 56 -H "Authorization: Basic $BASIC_AUTH" \ 57 http://localhost:9966/private/token \ 58 -d '{"scope":"spa"}' \ 59 -w "%{http_code}" -s -o $LAST_RESPONSE) 60 61 62 if [ "$STATUS" != "200" ] 63 then 64 exit_fail "Expected 200 OK. Got: $STATUS" 65 fi 66 67 TOKEN=$(jq -e -r .access_token < $LAST_RESPONSE) 68 69 echo " OK" >&2 70 71 echo -n "Refusing the password as bearer token in strict mode ..." >&2 72 73 STATUS=$(curl -H "Content-Type: application/json" \ 74 -H 'Authorization: Bearer secret-token:new_pw' \ 75 http://localhost:9966/private/products \ 76 -w "%{http_code}" -s -o "$LAST_RESPONSE") 77 78 if [ "$STATUS" != "401" ] || 79 [ "$(jq -r .code < "$LAST_RESPONSE")" != "2015" ] 80 then 81 jq < "$LAST_RESPONSE" >&2 82 exit_fail "Expected 401 with code 2015. Got: $STATUS" 83 fi 84 85 echo " OK" >&2 86 87 echo -n "Setting up bank account..." >&2 88 89 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 90 -H "Authorization: Bearer $TOKEN" \ 91 http://localhost:9966/private/accounts \ 92 -d '{"payto_uri":"payto://x-taler-bank/localhost:8082/43?receiver-name=user43"}' \ 93 -w "%{http_code}" -s -o /dev/null) 94 95 96 if [ "$STATUS" != "200" ] 97 then 98 exit_fail "Expected 200 OK. Got: $STATUS" 99 fi 100 101 echo " OK" >&2 102 103 # Check both refund endpoints with scoped bearer tokens. An unknown order 104 # must reach the refund handler (404/2005) only when the scope permits refunds. 105 for SCOPE in readonly order-simple order-pos order-pos:refreshable order-mgmt order-full 106 do 107 echo -n "Checking refund access for ${SCOPE} ..." >&2 108 STATUS=$(curl -H "Content-Type: application/json" \ 109 -H "Authorization: Basic $BASIC_AUTH" \ 110 http://localhost:9966/private/token \ 111 -d "$(jq -n --arg scope "$SCOPE" '{scope: $scope}')" \ 112 -w "%{http_code}" -s -o "$LAST_RESPONSE") 113 if [ "$STATUS" != "200" ] 114 then 115 cat "$LAST_RESPONSE" >&2 116 exit_fail "Expected 200, ${SCOPE} token created. Got: $STATUS" 117 fi 118 SCOPED_TOKEN=$(jq -e -r .access_token < "$LAST_RESPONSE") 119 120 case "$SCOPE" in 121 readonly|order-simple) 122 EXPECTED_STATUS=401 123 EXPECTED_CODE=2015 # TALER_EC_MERCHANT_GENERIC_UNAUTHORIZED 124 ;; 125 *) 126 EXPECTED_STATUS=404 127 EXPECTED_CODE=2005 # TALER_EC_MERCHANT_GENERIC_ORDER_UNKNOWN 128 ;; 129 esac 130 for ENDPOINT in refund refund-external 131 do 132 case "$ENDPOINT" in 133 refund) 134 REFUND_BODY='{"refund":"TESTKUDOS:1","reason":"scope test"}' 135 ;; 136 refund-external) 137 REFUND_BODY='{"method":"cash","id":"scope-test","amount":"TESTKUDOS:1","reason":"scope test"}' 138 ;; 139 esac 140 STATUS=$(curl -H "Content-Type: application/json" \ 141 -H "Authorization: Bearer $SCOPED_TOKEN" \ 142 "http://localhost:9966/private/orders/unknown-order/${ENDPOINT}" \ 143 -d "$REFUND_BODY" \ 144 -w "%{http_code}" -s -o "$LAST_RESPONSE") 145 if [ "$STATUS" != "$EXPECTED_STATUS" ] || 146 [ "$(jq -r .code < "$LAST_RESPONSE")" != "$EXPECTED_CODE" ] 147 then 148 cat "$LAST_RESPONSE" >&2 149 exit_fail "Expected ${EXPECTED_STATUS}/${EXPECTED_CODE} for ${SCOPE} on ${ENDPOINT}. Got: $STATUS" 150 fi 151 done 152 echo " OK" >&2 153 done 154 155 # Kill merchant 156 kill -TERM "$SETUP_PID" 157 wait 158 unset SETUP_PID 159 160 setup -c test_template.conf \ 161 -ef \ 162 -u "exchange-account-2" \ 163 -r "merchant-exchange-default" 164 165 NEW_SECRET="different_value" 166 167 taler-merchant-exchangekeyupdate \ 168 -c "${CONF}" \ 169 -L DEBUG \ 170 -t \ 171 2> taler-merchant-exchangekeyupdate2.log 172 taler-merchant-passwd \ 173 -c "${CONF}" \ 174 -L DEBUG \ 175 "$NEW_SECRET" \ 176 2> taler-merchant-passwd.log 177 taler-merchant-httpd \ 178 -c "${CONF}" \ 179 -L DEBUG \ 180 2> taler-merchant-httpd2.log & 181 # Install cleanup handler (except for kill -9) 182 trap my_cleanup EXIT 183 184 echo -n "Waiting for the merchant..." >&2 185 # Wait for merchant to be available (usually the slowest) 186 for n in $(seq 1 50) 187 do 188 echo -n "." >&2 189 sleep 0.1 190 OK=0 191 # merchant 192 wget --waitretry=0 \ 193 --timeout=1 \ 194 http://localhost:9966/ \ 195 -o /dev/null \ 196 -O /dev/null \ 197 >/dev/null || continue 198 OK=1 199 break 200 done 201 202 if [ "x$OK" != "x1" ] 203 then 204 exit_fail "Failed to (re)start merchant backend" 205 fi 206 207 echo " OK" >&2 208 209 BASIC_AUTH=$(echo -n "admin:$NEW_SECRET" | base64) 210 211 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 212 -H "Authorization: Basic $BASIC_AUTH" \ 213 http://localhost:9966/private/token \ 214 -d '{"scope":"spa"}' \ 215 -w "%{http_code}" -s -o $LAST_RESPONSE) 216 217 218 if [ "$STATUS" != "200" ] 219 then 220 exit_fail "Expected 200 OK. Got: $STATUS" 221 fi 222 223 TOKEN=$(jq -e -r .access_token < $LAST_RESPONSE) 224 225 echo -n "Making sure merchant KYC data is current ..." >&2 226 227 taler-merchant-kyccheck \ 228 -c "${CONF}" \ 229 -L DEBUG \ 230 -t \ 231 2> taler-merchant-kyccheck.log 232 233 sleep 1 234 echo " OK" 235 236 echo -n "Creating order to test auth is ok..." >&2 237 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 238 'http://localhost:9966/private/orders' \ 239 -H 'Authorization: Bearer '"$TOKEN" \ 240 -d '{"order":{"amount":"TESTKUDOS:1","summary":"payme"}}' \ 241 -w "%{http_code}" -s -o "$LAST_RESPONSE") 242 243 if [ "$STATUS" != "200" ] 244 then 245 cat "$LAST_RESPONSE" >&2 246 exit_fail "Expected 200, order created. got: $STATUS" 247 fi 248 249 ORDER_ID=$(jq -e -r .order_id < "$LAST_RESPONSE") 250 ORD_TOKEN=$(jq -e -r .token < "$LAST_RESPONSE") 251 252 STATUS=$(curl "http://localhost:9966/private/orders/${ORDER_ID}" \ 253 -H 'Authorization: Bearer '"$TOKEN" \ 254 -w "%{http_code}" -s -o "$LAST_RESPONSE") 255 256 if [ "$STATUS" != "200" ] 257 then 258 cat "$LAST_RESPONSE" >&2 259 exit_fail "Expected 200, getting order info before claming it. got: $STATUS" 260 fi 261 262 PAY_URL=$(jq -e -r .taler_pay_uri < "$LAST_RESPONSE") 263 264 echo "OK order ${ORDER_ID} with ${ORD_TOKEN} and ${PAY_URL}" >&2 265 266 echo -n "Configuring 'second' instance ..." >&2 267 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 268 -H 'Authorization: Bearer '"$TOKEN" \ 269 http://localhost:9966/management/instances \ 270 -d '{"auth":{"method":"token","password":"second"},"id":"second","name":"second","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \ 271 -w "%{http_code}" -s -o "$LAST_RESPONSE") 272 273 if [ "$STATUS" != "204" ] 274 then 275 cat "$LAST_RESPONSE" >&2 276 exit_fail "Expected 204, instance created. got: $STATUS" 277 fi 278 279 echo "OK" >&2 280 281 echo -n "Configuring 'third' instance ..." >&2 282 283 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 284 -H 'Authorization: Bearer '"$TOKEN" \ 285 http://localhost:9966/management/instances \ 286 -d '{"auth":{"method":"token","password":"third"},"id":"third","name":"third","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \ 287 -w "%{http_code}" -s -o "$LAST_RESPONSE") 288 289 if [ "$STATUS" != "204" ] 290 then 291 cat "$LAST_RESPONSE" >&2 292 exit_fail "Expected 204, instance created. got: $STATUS" 293 fi 294 295 echo "OK" >&2 296 297 echo -n "Updating 'second' instance token using the 'new_one' auth token..." >&2 298 299 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 300 -H 'Authorization: Bearer '"$TOKEN" \ 301 http://localhost:9966/management/instances/second/auth \ 302 -d '{"method":"token","password":"new_one"}' \ 303 -w "%{http_code}" -s -o "$LAST_RESPONSE") 304 305 if [ "$STATUS" != "204" ] 306 then 307 cat "$LAST_RESPONSE" >&2 308 exit_fail "Expected 204, instance auth token changed. got: $STATUS" 309 fi 310 NEW_SECRET="new_one" 311 echo " OK" >&2 312 313 BASIC_AUTH2=$(echo -n second:$NEW_SECRET | base64) 314 315 echo -n "Requesting login token..." >&2 316 317 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 318 -H 'Authorization: Basic '"$BASIC_AUTH2" \ 319 http://localhost:9966/instances/second/private/token \ 320 -d '{"scope":"readonly","refreshable":true}' \ 321 -w "%{http_code}" -s -o "$LAST_RESPONSE") 322 323 if [ "$STATUS" != "200" ] 324 then 325 jq < "$LAST_RESPONSE" >&2 326 exit_fail "Expected 200, login token created. got: $STATUS" 327 fi 328 329 TOKEN=$(jq -e -r .access_token < "$LAST_RESPONSE") 330 331 echo " OK" >&2 332 333 echo -n "Requesting login token... (spa)" >&2 334 335 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 336 -H 'Authorization: Basic '"$BASIC_AUTH2" \ 337 http://localhost:9966/instances/second/private/token \ 338 -d '{"scope":"spa"}' \ 339 -w "%{http_code}" -s -o "$LAST_RESPONSE") 340 341 if [ "$STATUS" != "200" ] 342 then 343 jq < "$LAST_RESPONSE" >&2 344 exit_fail "Expected 200, login token created. got: $STATUS" 345 fi 346 347 RWTOKEN=$(jq -e -r .access_token < "$LAST_RESPONSE") 348 349 echo " OK" >&2 350 351 echo -n "Using login token..." >&2 352 353 STATUS=$(curl "http://localhost:9966/instances/second/private/orders" \ 354 -H 'Authorization: Bearer '"$TOKEN" \ 355 -w "%{http_code}" -s -o "$LAST_RESPONSE") 356 357 if [ "$STATUS" != "200" ] 358 then 359 jq < "$LAST_RESPONSE" >&2 360 exit_fail "Expected 200, getting orders. got: $STATUS" 361 fi 362 363 echo " OK" >&2 364 365 echo -n "Updating 'second' instance token using the 'second' auth token..." >&2 366 367 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 368 -H 'Authorization: Bearer '"$RWTOKEN" \ 369 http://localhost:9966/instances/second/private/auth \ 370 -d '{"method":"token","password":"again"}' \ 371 -w "%{http_code}" -s -o "$LAST_RESPONSE") 372 373 if [ "$STATUS" != "401" ] || 374 [ "$(jq -r .code < "$LAST_RESPONSE")" != "2604" ] 375 then 376 cat "$LAST_RESPONSE" >&2 377 exit_fail "Expected missing old password to fail with 401/2604. Got: $STATUS" 378 fi 379 380 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 381 -H 'Authorization: Bearer '"$RWTOKEN" \ 382 http://localhost:9966/instances/second/private/auth \ 383 -d '{"method":"token","password":"again","old_password":"wrong"}' \ 384 -w "%{http_code}" -s -o "$LAST_RESPONSE") 385 386 if [ "$STATUS" != "401" ] || 387 [ "$(jq -r .code < "$LAST_RESPONSE")" != "2604" ] 388 then 389 cat "$LAST_RESPONSE" >&2 390 exit_fail "Expected wrong old password to fail with 401/2604. Got: $STATUS" 391 fi 392 393 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 394 -H 'Authorization: Bearer '"$RWTOKEN" \ 395 http://localhost:9966/instances/second/private/auth \ 396 -d '{"method":"token","password":"again","old_password":"new_one"}' \ 397 -w "%{http_code}" -s -o "$LAST_RESPONSE") 398 399 BASIC_AUTH2=$(echo -n second:again | base64) 400 401 if [ "$STATUS" != "204" ] 402 then 403 cat $LAST_RESPONSE >&2 404 exit_fail "Expected 204, instance not authorized. got: $STATUS" 405 fi 406 407 echo " OK" >&2 408 409 echo -n "Updating 'third' instance token using the 'second' auth token..." >&2 410 411 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 412 -H 'Authorization: Bearer '"$RWTOKEN" \ 413 http://localhost:9966/management/instances/third/auth \ 414 -d '{"method":"token","password":"new_one"}' \ 415 -w "%{http_code}" -s -o "$LAST_RESPONSE") 416 417 if [ "$STATUS" != "401" ] 418 then 419 cat $LAST_RESPONSE >&2 420 exit_fail "Expected 401, instance not authorized. got: $STATUS" 421 fi 422 423 echo " OK" >&2 424 425 echo -n "Refreshing login token... (expected failure)" >&2 426 427 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 428 -H 'Authorization: Bearer '"$TOKEN" \ 429 http://localhost:9966/instances/second/private/token \ 430 -d '{"scope":"spa","refreshable":true}' \ 431 -w "%{http_code}" -s -o "$LAST_RESPONSE") 432 433 if [ "$STATUS" != "403" ] 434 then 435 jq < "$LAST_RESPONSE" >&2 436 exit_fail "Expected 403, refused to upgrade login token. got: $STATUS" 437 fi 438 439 echo " OK" >&2 440 441 echo -n "Refreshing login token... (expected failure)" >&2 442 443 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 444 -H 'Authorization: Bearer '"$RWTOKEN" \ 445 http://localhost:9966/instances/second/private/token \ 446 -d '{"scope":"spa","refreshable":true}' \ 447 -w "%{http_code}" -s -o "$LAST_RESPONSE") 448 449 if [ "$STATUS" != "401" ] 450 then 451 jq < "$LAST_RESPONSE" >&2 452 exit_fail "Expected 401, refused to upgrade login token. got: $STATUS" 453 fi 454 455 echo " OK" >&2 456 457 echo -n "Creating refreshable login token..." >&2 458 459 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 460 -H 'Authorization: Basic '"$BASIC_AUTH2" \ 461 http://localhost:9966/instances/second/private/token \ 462 -d '{"scope":"spa:refreshable"}' \ 463 -w "%{http_code}" -s -o "$LAST_RESPONSE") 464 465 if [ "$STATUS" != "200" ] 466 then 467 jq < "$LAST_RESPONSE" >&2 468 exit_fail "Expected 200, login token created. got: $STATUS" 469 fi 470 471 RWTOKEN=$(jq -e -r .access_token < "$LAST_RESPONSE") 472 473 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 474 -H 'Authorization: Bearer '"$RWTOKEN" \ 475 http://localhost:9966/instances/second/private/token \ 476 -d '{"scope":"spa","refreshable":true}' \ 477 -w "%{http_code}" -s -o "$LAST_RESPONSE") 478 479 if [ "$STATUS" != "200" ] 480 then 481 jq < "$LAST_RESPONSE" >&2 482 exit_fail "Expected 200. got: $STATUS" 483 fi 484 485 echo " OK" >&2 486 487 488 echo -n "Requesting another login token... (read)" >&2 489 490 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 491 -H 'Authorization: Basic '"$BASIC_AUTH2" \ 492 http://localhost:9966/instances/second/private/token \ 493 -d '{"scope":"readonly", "refreshable": false}' \ 494 -w "%{http_code}" -s -o "$LAST_RESPONSE") 495 496 if [ "$STATUS" != "200" ] 497 then 498 jq < "$LAST_RESPONSE" >&2 499 exit_fail "Expected 200, login token created. got: $STATUS" 500 fi 501 502 RTOKEN=$(jq -e -r .access_token < "$LAST_RESPONSE") 503 504 echo " OK" >&2 505 506 echo -n "Requesting another login token... (read:refreshable)" >&2 507 508 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 509 -H 'Authorization: Basic '"$BASIC_AUTH2" \ 510 http://localhost:9966/instances/second/private/token \ 511 -d '{"scope":"readonly:refreshable", "description": "readonly but refreshable"}' \ 512 -w "%{http_code}" -s -o "$LAST_RESPONSE") 513 514 if [ "$STATUS" != "200" ] 515 then 516 jq < "$LAST_RESPONSE" >&2 517 exit_fail "Expected 200, login token created. got: $STATUS" 518 fi 519 520 RTOKEN=$(jq -e -r .access_token < "$LAST_RESPONSE") 521 522 echo " OK" >&2 523 524 echo "Getting last 2 login tokens." >&2 525 526 STATUS=$(curl -H "Content-Type: application/json" \ 527 -H "Authorization: Bearer $RWTOKEN" \ 528 'http://localhost:9966/instances/second/private/tokens?limit=-2' \ 529 -w "%{http_code}" -s -o $LAST_RESPONSE) 530 531 if [ "$STATUS" != "200" ] 532 then 533 jq < "$LAST_RESPONSE" >&2 534 exit_fail "Expected 200 OK. Got: $STATUS" 535 fi 536 537 TOKEN_SERIAL=$(jq -e -r .tokens[0].serial < "$LAST_RESPONSE") 538 539 echo -n "Deleting second login token by serial..." >&2 540 541 STATUS=$(curl -H "Content-Type: application/json" -X DELETE \ 542 -H 'Authorization: Bearer '"$RWTOKEN" \ 543 http://localhost:9966/instances/second/private/tokens/$TOKEN_SERIAL \ 544 -w "%{http_code}" -s -o "$LAST_RESPONSE") 545 546 if [ "$STATUS" != "204" ] 547 then 548 jq < "$LAST_RESPONSE" >&2 549 exit_fail "Expected 204, login token deleted. got: $STATUS" 550 fi 551 echo " OK" >&2 552 553 echo -n "Using deleted login token $RTOKEN..." >&2 554 555 STATUS=$(curl "http://localhost:9966/instances/second/private/orders" \ 556 -H 'Authorization: Bearer '"$RTOKEN" \ 557 -w "%{http_code}" -s -o "$LAST_RESPONSE") 558 559 if [ "$STATUS" != "401" ] 560 then 561 jq < "$LAST_RESPONSE" >&2 562 exit_fail "Expected 401, token was deleted. got: $STATUS" 563 fi 564 565 echo " OK" >&2 566 567 568 echo -n "Deleting login token..." >&2 569 570 STATUS=$(curl -H "Content-Type: application/json" -X DELETE \ 571 -H 'Authorization: Bearer '"$TOKEN" \ 572 http://localhost:9966/instances/second/private/token \ 573 -w "%{http_code}" -s -o "$LAST_RESPONSE") 574 575 if [ "$STATUS" != "204" ] 576 then 577 jq < "$LAST_RESPONSE" >&2 578 exit_fail "Expected 204, login token deleted. got: $STATUS" 579 fi 580 echo " OK" >&2 581 582 echo -n "Using deleted login token..." >&2 583 584 STATUS=$(curl "http://localhost:9966/instances/second/private/orders" \ 585 -H 'Authorization: Bearer '"$TOKEN" \ 586 -w "%{http_code}" -s -o "$LAST_RESPONSE") 587 588 if [ "$STATUS" != "401" ] 589 then 590 jq < "$LAST_RESPONSE" >&2 591 exit_fail "Expected 401, token was deleted. got: $STATUS" 592 fi 593 594 echo " OK" >&2 595 596 597 echo "Test PASSED" 598 599 exit 0