github.com/minio/mc@v0.0.0-20240503112107-b471de8d1882/functional-tests.sh (about) 1 #!/bin/bash 2 # 3 # Copyright (c) 2015-2023 MinIO, Inc. 4 # 5 # This file is part of MinIO Object Storage stack 6 # 7 # This program is free software: you can redistribute it and/or modify 8 # it under the terms of the GNU Affero General Public License as published by 9 # the Free Software Foundation, either version 3 of the License, or 10 # (at your option) any later version. 11 # 12 # This program is distributed in the hope that it will be useful 13 # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 # GNU Affero General Public License for more details. 16 # 17 # You should have received a copy of the GNU Affero General Public License 18 # along with this program. If not, see <http://www.gnu.org/licenses/>. 19 # 20 21 ################################################################################ 22 # 23 # This script is usable by mc functional tests, mint tests and MinIO verification 24 # tests. 25 # 26 # * As mc functional tests, just run this script. It uses mc executable binary 27 # in current working directory or in the path. The tests uses play.min.io 28 # as MinIO server. 29 # 30 # * For other, call this script with environment variables MINT_MODE, 31 # MINT_DATA_DIR, SERVER_ENDPOINT, ACCESS_KEY, SECRET_KEY and ENABLE_HTTPS. It 32 # uses mc executable binary in current working directory and uses given MinIO 33 # server to run tests. MINT_MODE is set by mint to specify what category of 34 # tests to run. 35 # 36 ################################################################################ 37 38 # Force bytewise sorting for CLI tools 39 LANG=C 40 41 if [ -n "$MINT_MODE" ]; then 42 if [ -z "${MINT_DATA_DIR+x}" ]; then 43 echo "MINT_DATA_DIR not defined" 44 exit 1 45 fi 46 if [ -z "${SERVER_ENDPOINT+x}" ]; then 47 echo "SERVER_ENDPOINT not defined" 48 exit 1 49 fi 50 if [ -z "${ACCESS_KEY+x}" ]; then 51 echo "ACCESS_KEY not defined" 52 exit 1 53 fi 54 if [ -z "${SECRET_KEY+x}" ]; then 55 echo "SECRET_KEY not defined" 56 exit 1 57 fi 58 fi 59 60 if [ -z "${SERVER_ENDPOINT+x}" ]; then 61 SERVER_ENDPOINT="play.min.io" 62 ACCESS_KEY="Q3AM3UQ867SPQQA43P2F" 63 SECRET_KEY="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG" 64 ENABLE_HTTPS=1 65 fi 66 67 # If you want to run the complete site cleaning test, set this variable to true 68 COMPLETE_RB_TEST=true 69 70 WORK_DIR="$PWD" 71 DATA_DIR="$MINT_DATA_DIR" 72 if [ -z "$MINT_MODE" ]; then 73 WORK_DIR="$PWD/.run-$RANDOM" 74 DATA_DIR="$WORK_DIR/data" 75 fi 76 77 FILE_0_B="$DATA_DIR/datafile-0-b" 78 FILE_1_MB="$DATA_DIR/datafile-1-MB" 79 FILE_65_MB="$DATA_DIR/datafile-65-MB" 80 declare FILE_0_B_MD5SUM 81 declare FILE_1_MB_MD5SUM 82 declare FILE_65_MB_MD5SUM 83 84 ENDPOINT="https://$SERVER_ENDPOINT" 85 if [ "$ENABLE_HTTPS" != "1" ]; then 86 ENDPOINT="http://$SERVER_ENDPOINT" 87 fi 88 89 SERVER_ALIAS="myminio" 90 SERVER_ALIAS_TLS="myminio-ssl" 91 92 BUCKET_NAME="mc-test-bucket-$RANDOM" 93 WATCH_OUT_FILE="$WORK_DIR/watch.out-$RANDOM" 94 95 MC_CONFIG_DIR="/tmp/.mc-$RANDOM" 96 MC="$PWD/mc" 97 declare -a MC_CMD 98 99 function get_md5sum() 100 { 101 filename="$1" 102 out=$(md5sum "$filename" 2>/dev/null) 103 rv=$? 104 if [ "$rv" -eq 0 ]; then 105 echo $(awk '{ print $1 }' <<< "$out") 106 fi 107 108 return "$rv" 109 } 110 111 function get_time() 112 { 113 date +%s%N 114 } 115 116 function get_duration() 117 { 118 start_time=$1 119 end_time=$(get_time) 120 121 echo $(( (end_time - start_time) / 1000000 )) 122 } 123 124 function log_success() 125 { 126 if [ -n "$MINT_MODE" ]; then 127 printf '{"name": "mc", "duration": "%d", "function": "%s", "status": "PASS"}\n' "$(get_duration "$1")" "$2" 128 fi 129 } 130 131 function show() 132 { 133 if [ -z "$MINT_MODE" ]; then 134 func_name="$1" 135 echo "Running $func_name()" 136 fi 137 } 138 139 function show_on_success() 140 { 141 rv="$1" 142 shift 143 144 if [ "$rv" -eq 0 ]; then 145 echo "$@" 146 fi 147 148 return "$rv" 149 } 150 151 function show_on_failure() 152 { 153 rv="$1" 154 shift 155 156 if [ "$rv" -ne 0 ]; then 157 echo "$@" 158 fi 159 160 return "$rv" 161 } 162 163 function assert() 164 { 165 expected_rv="$1" 166 shift 167 start_time="$1" 168 shift 169 func_name="$1" 170 shift 171 172 err=$("$@") 173 rv=$? 174 if [ "$rv" -ne "$expected_rv" ]; then 175 if [ -n "$MINT_MODE" ]; then 176 err=$(printf "$err" | python -c 'import sys,json; print(json.dumps(sys.stdin.read()))') 177 ## err is already JSON string, no need to double quote 178 printf '{"name": "mc", "duration": "%d", "function": "%s", "status": "FAIL", "error": %s}\n' "$(get_duration "$start_time")" "$func_name" "$err" 179 else 180 echo "mc: $func_name: $err" 181 fi 182 183 if [ "$rv" -eq 0 ]; then 184 exit 1 185 fi 186 187 exit "$rv" 188 fi 189 190 return 0 191 } 192 193 function assert_success() { 194 assert 0 "$@" 195 } 196 197 function assert_failure() { 198 assert 1 "$@" 199 } 200 201 function mc_cmd() 202 { 203 cmd=( "${MC_CMD[@]}" "$@" ) 204 err_file="$WORK_DIR/cmd.out.$RANDOM" 205 206 "${cmd[@]}" >"$err_file" 2>&1 207 rv=$? 208 if [ "$rv" -ne 0 ]; then 209 printf '%q ' "${cmd[@]}" 210 echo " >>> " 211 cat "$err_file" 212 fi 213 214 rm -f "$err_file" 215 return "$rv" 216 } 217 218 function check_md5sum() 219 { 220 expected_checksum="$1" 221 shift 222 filename="$@" 223 224 checksum="$(get_md5sum "$filename")" 225 rv=$? 226 if [ "$rv" -ne 0 ]; then 227 echo "unable to get md5sum for $filename" 228 return "$rv" 229 fi 230 231 if [ "$checksum" != "$expected_checksum" ]; then 232 echo "$filename: md5sum mismatch" 233 return 1 234 fi 235 236 return 0 237 } 238 239 function test_make_bucket() 240 { 241 show "${FUNCNAME[0]}" 242 243 start_time=$(get_time) 244 bucket_name="mc-test-bucket-$RANDOM" 245 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mb "${SERVER_ALIAS}/${bucket_name}" 246 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rb "${SERVER_ALIAS}/${bucket_name}" 247 248 log_success "$start_time" "${FUNCNAME[0]}" 249 } 250 251 function test_make_bucket_error() { 252 show "${FUNCNAME[0]}" 253 254 start_time=$(get_time) 255 bucket_name="MC-test%bucket%$RANDOM" 256 assert_failure "$start_time" "${FUNCNAME[0]}" mc_cmd mb "${SERVER_ALIAS}/${bucket_name}" 257 258 log_success "$start_time" "${FUNCNAME[0]}" 259 } 260 261 function test_rb() 262 { 263 show "${FUNCNAME[0]}" 264 265 start_time=$(get_time) 266 bucket1="mc-test-bucket-$RANDOM-1" 267 bucket2="mc-test-bucket-$RANDOM-2" 268 object_name="mc-test-object-$RANDOM" 269 270 # Tets rb when the bucket is empty 271 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mb "${SERVER_ALIAS}/${bucket1}" 272 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rb "${SERVER_ALIAS}/${bucket1}" 273 274 # Test rb with --force flag when the bucket is not empty 275 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mb "${SERVER_ALIAS}/${bucket1}" 276 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${FILE_1_MB}" "${SERVER_ALIAS}/${bucket1}/${object_name}" 277 assert_failure "$start_time" "${FUNCNAME[0]}" mc_cmd rb "${SERVER_ALIAS}/${bucket1}" 278 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rb --force "${SERVER_ALIAS}/${bucket1}" 279 280 # Test rb with --force and --dangerous to remove a site content 281 if [ "${COMPLETE_RB_TEST}" == "true" ]; then 282 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mb "${SERVER_ALIAS}/${bucket1}" 283 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mb "${SERVER_ALIAS}/${bucket2}" 284 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${FILE_1_MB}" "${SERVER_ALIAS}/${bucket1}/${object_name}" 285 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${FILE_1_MB}" "${SERVER_ALIAS}/${bucket2}/${object_name}" 286 assert_failure "$start_time" "${FUNCNAME[0]}" mc_cmd rb --force "${SERVER_ALIAS}/" 287 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rb --force --dangerous "${SERVER_ALIAS}" 288 fi 289 290 log_success "$start_time" "${FUNCNAME[0]}" 291 } 292 293 function setup() 294 { 295 start_time=$(get_time) 296 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mb "${SERVER_ALIAS}/${BUCKET_NAME}" 297 } 298 299 function teardown() 300 { 301 start_time=$(get_time) 302 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rb --force "${SERVER_ALIAS}/${BUCKET_NAME}" 303 } 304 305 # Test mc ls on a S3 prefix where a lower similar prefix exists as well e.g. dir-foo/ and dir/ 306 function test_list_dir() 307 { 308 show "${FUNCNAME[0]}" 309 310 start_time=$(get_time) 311 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/dir-foo/object1" 312 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/dir/object2" 313 diff -bB <(echo "object2") <("${MC_CMD[@]}" --json ls "${SERVER_ALIAS}/${BUCKET_NAME}/dir" | jq -r '.key') >/dev/null 2>&1 314 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "unexpected listing dir" 315 316 # Cleanup 317 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/dir-foo/${object_name}" 318 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/dir/${object_name}" 319 320 log_success "$start_time" "${FUNCNAME[0]}" 321 } 322 323 function test_od_object() { 324 show "${FUNCNAME[0]}" 325 326 start_time=$(get_time) 327 object_name="mc-test-object-$RANDOM" 328 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd od if="${FILE_1_MB}" of="${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 329 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd od of="${FILE_1_MB}" if="${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 330 331 log_success "$start_time" "${FUNCNAME[0]}" 332 } 333 334 function test_put_object() 335 { 336 show "${FUNCNAME[0]}" 337 338 start_time=$(get_time) 339 object_name="mc-test-object-$RANDOM" 340 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 341 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 342 343 log_success "$start_time" "${FUNCNAME[0]}" 344 } 345 346 function test_put_object_error() 347 { 348 show "${FUNCNAME[0]}" 349 start_time=$(get_time) 350 351 object_long_name=$(printf "mc-test-object-%01100d" 1) 352 assert_failure "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_long_name}" 353 354 log_success "$start_time" "${FUNCNAME[0]}" 355 } 356 357 function test_put_object_multipart() 358 { 359 show "${FUNCNAME[0]}" 360 361 start_time=$(get_time) 362 object_name="mc-test-object-$RANDOM" 363 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${FILE_65_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 364 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 365 366 log_success "$start_time" "${FUNCNAME[0]}" 367 } 368 369 function test_put_object_0byte() 370 { 371 show "${FUNCNAME[0]}" 372 373 start_time=$(get_time) 374 object_name="mc-test-object-$RANDOM" 375 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${FILE_0_B}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 376 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" "${object_name}.downloaded" 377 assert_success "$start_time" "${FUNCNAME[0]}" check_md5sum "$FILE_0_B_MD5SUM" "${object_name}.downloaded" 378 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm "${object_name}.downloaded" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 379 380 log_success "$start_time" "${FUNCNAME[0]}" 381 } 382 383 ## Test mc cp command with storage-class flag set 384 function test_put_object_with_storage_class() 385 { 386 show "${FUNCNAME[0]}" 387 388 start_time=$(get_time) 389 object_name="mc-test-object-$RANDOM" 390 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp --storage-class REDUCED_REDUNDANCY "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 391 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 392 393 log_success "$start_time" "${FUNCNAME[0]}" 394 } 395 396 ## Test mc cp command with storage-class flag set to incorrect value 397 function test_put_object_with_storage_class_error() 398 { 399 show "${FUNCNAME[0]}" 400 401 start_time=$(get_time) 402 object_name="mc-test-object-$RANDOM" 403 assert_failure "$start_time" "${FUNCNAME[0]}" mc_cmd cp --storage-class REDUCED "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 404 405 log_success "$start_time" "${FUNCNAME[0]}" 406 } 407 408 ## Test mc cp command with valid metadata string 409 function test_put_object_with_metadata() 410 { 411 show "${FUNCNAME[0]}" 412 413 start_time=$(get_time) 414 object_name="mc-test-object-$RANDOM" 415 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp --attr key1=val1\;key2=val2 "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 416 diff -bB <(echo "val1") <("${MC_CMD[@]}" --json stat "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" | jq -r '.metadata."X-Amz-Meta-Key1"') >/dev/null 2>&1 417 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "unable to put object with metadata" 418 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 419 log_success "$start_time" "${FUNCNAME[0]}" 420 421 } 422 423 function test_get_object() 424 { 425 show "${FUNCNAME[0]}" 426 427 start_time=$(get_time) 428 object_name="mc-test-object-$RANDOM" 429 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 430 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" "${object_name}.downloaded" 431 assert_success "$start_time" "${FUNCNAME[0]}" check_md5sum "$FILE_1_MB_MD5SUM" "${object_name}.downloaded" 432 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm "${object_name}.downloaded" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 433 434 log_success "$start_time" "${FUNCNAME[0]}" 435 } 436 437 function test_get_object_multipart() 438 { 439 show "${FUNCNAME[0]}" 440 441 start_time=$(get_time) 442 object_name="mc-test-object-$RANDOM" 443 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${FILE_65_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 444 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" "${object_name}.downloaded" 445 assert_success "$start_time" "${FUNCNAME[0]}" check_md5sum "$FILE_65_MB_MD5SUM" "${object_name}.downloaded" 446 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm "${object_name}.downloaded" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 447 448 log_success "$start_time" "${FUNCNAME[0]}" 449 } 450 451 function test_presigned_post_policy_error() 452 { 453 show "${FUNCNAME[0]}" 454 455 start_time=$(get_time) 456 object_name="mc-test-object-$RANDOM" 457 458 out=$("${MC_CMD[@]}" --json share upload "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}") 459 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "unable to get presigned post policy and put object url" 460 461 # Support IPv6 address, IPv6 is specifed as [host]:9000 form, we should 462 # replace '['']' with their escaped values as '\[' '\]'. 463 # 464 # Without escaping '['']', 'sed' command interprets them as expressions 465 # which fails our requirement of replacing $endpoint/$bucket URLs in the 466 # subsequent operations. 467 endpoint=$(echo "$ENDPOINT" | sed 's|[][]|\\&|g') 468 469 # Extract share field of json output, and append object name to the URL 470 upload=$(echo "$out" | jq -r .share | sed "s|<FILE>|$FILE_1_MB|g" | sed "s|curl|curl -sSg|g" | sed "s|${endpoint}/${BUCKET_NAME}/|${endpoint}/${BUCKET_NAME}/${object_name}|g") 471 472 # In case of virtual host style URL path, the previous replace would have failed. 473 # One of the following two commands will append the object name in that scenario. 474 upload=$(echo "$upload" | sed "s|http://${BUCKET_NAME}.${SERVER_ENDPOINT}/|http://${BUCKET_NAME}.${SERVER_ENDPOINT}/${object_name}|g") 475 upload=$(echo "$upload" | sed "s|https://${BUCKET_NAME}.${SERVER_ENDPOINT}/|https://${BUCKET_NAME}.${SERVER_ENDPOINT}/${object_name}|g") 476 477 ret=$($upload 2>&1 | grep -oP '(?<=Code>)[^<]+') 478 # Check if the command execution failed. 479 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "unknown failure in upload of $FILE_1_MB using presigned post policy" 480 if [ -z "$ret" ]; then 481 482 # Check if the upload succeeded. We expect it to fail. 483 assert_failure "$start_time" "${FUNCNAME[0]}" show_on_success 0 "upload of $FILE_1_MB using presigned post policy should have failed" 484 fi 485 486 if [ "$ret" != "MethodNotAllowed" ]; then 487 assert_failure "$start_time" "${FUNCNAME[0]}" show_on_success 0 "upload of $FILE_1_MB using presigned post policy should have failed with MethodNotAllowed error, instead failed with $ret error" 488 fi 489 log_success "$start_time" "${FUNCNAME[0]}" 490 } 491 492 function test_presigned_put_object() 493 { 494 show "${FUNCNAME[0]}" 495 496 start_time=$(get_time) 497 object_name="mc-test-object-$RANDOM" 498 499 out=$("${MC_CMD[@]}" --json share upload "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}") 500 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "unable to get presigned put object url" 501 upload=$(echo "$out" | jq -r .share | sed "s|<FILE>|$FILE_1_MB|g" | sed "s|curl|curl -sSg|g") 502 $upload >/dev/null 2>&1 503 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "unable to upload $FILE_1_MB presigned put object url" 504 505 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" "${object_name}.downloaded" 506 assert_success "$start_time" "${FUNCNAME[0]}" check_md5sum "$FILE_1_MB_MD5SUM" "${object_name}.downloaded" 507 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm "${object_name}.downloaded" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 508 509 log_success "$start_time" "${FUNCNAME[0]}" 510 } 511 512 function test_presigned_get_object() 513 { 514 show "${FUNCNAME[0]}" 515 516 start_time=$(get_time) 517 object_name="mc-test-object-$RANDOM" 518 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 519 520 out=$("${MC_CMD[@]}" --json share download "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}") 521 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "unable to get presigned get object url" 522 download_url=$(echo "$out" | jq -r .share) 523 curl -sSg --output "${object_name}.downloaded" -X GET "$download_url" 524 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "unable to download $download_url" 525 526 assert_success "$start_time" "${FUNCNAME[0]}" check_md5sum "$FILE_1_MB_MD5SUM" "${object_name}.downloaded" 527 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm "${object_name}.downloaded" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 528 529 log_success "$start_time" "${FUNCNAME[0]}" 530 } 531 532 function test_cat_object() 533 { 534 show "${FUNCNAME[0]}" 535 536 start_time=$(get_time) 537 object_name="mc-test-object-$RANDOM" 538 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 539 "${MC_CMD[@]}" cat "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" > "${object_name}.downloaded" 540 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "unable to download object using 'mc cat'" 541 assert_success "$start_time" "${FUNCNAME[0]}" check_md5sum "$FILE_1_MB_MD5SUM" "${object_name}.downloaded" 542 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm "${object_name}.downloaded" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 543 544 log_success "$start_time" "${FUNCNAME[0]}" 545 } 546 547 function test_cat_stdin() 548 { 549 show "${FUNCNAME[0]}" 550 551 start_time=$(get_time) 552 object_name="mc-test-object-$RANDOM" 553 bucket_name="mc-test-bucket-$RANDOM" 554 "${MC_CMD[@]}" mb "${SERVER_ALIAS}/${bucket_name}" 555 echo "testcontent" | "${MC_CMD[@]}" pipe "${SERVER_ALIAS}/${bucket_name}/${object_name}" 556 "${MC_CMD[@]}" cat "${SERVER_ALIAS}/${bucket_name}/${object_name}" > stdout.output 557 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "unable to redirect stdin to stdout using 'mc cat'" 558 assert_success "$start_time" "${FUNCNAME[0]}" check_md5sum "42ed9fb3563d8e9c7bb522be443033f4" stdout.output 559 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm stdout.output 560 561 log_success "$start_time" "${FUNCNAME[0]}" 562 } 563 564 565 function test_mirror_list_objects() 566 { 567 show "${FUNCNAME[0]}" 568 569 start_time=$(get_time) 570 bucket_name="mc-test-bucket-$RANDOM" 571 object_name="mc-test-object-$RANDOM" 572 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mb "${SERVER_ALIAS}/${bucket_name}" 573 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mirror "$DATA_DIR" "${SERVER_ALIAS}/${bucket_name}" 574 575 diff -bB <(ls "$DATA_DIR") <("${MC_CMD[@]}" --json ls "${SERVER_ALIAS}/${bucket_name}/" | jq -r .key) >/dev/null 2>&1 576 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "mirror and list differs" 577 578 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rb --force "${SERVER_ALIAS}/${bucket_name}" 579 580 log_success "$start_time" "${FUNCNAME[0]}" 581 } 582 583 ## Tests mc mirror command with --storage-class flag set 584 function test_mirror_list_objects_storage_class() 585 { 586 show "${FUNCNAME[0]}" 587 588 start_time=$(get_time) 589 bucket_name="mc-test-bucket-$RANDOM" 590 object_name="mc-test-object-$RANDOM" 591 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mb "${SERVER_ALIAS}/${bucket_name}" 592 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mirror --storage-class REDUCED_REDUNDANCY "$DATA_DIR" "${SERVER_ALIAS}/${bucket_name}" 593 594 diff -bB <(ls "$DATA_DIR") <("${MC_CMD[@]}" --json ls "${SERVER_ALIAS}/${bucket_name}/" | jq -r .key) >/dev/null 2>&1 595 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "mirror and list differs" 596 597 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rb --force "${SERVER_ALIAS}/${bucket_name}" 598 599 log_success "$start_time" "${FUNCNAME[0]}" 600 } 601 602 ## Tests find command with --older-than set to 1day, should be empty. 603 function test_find_empty() { 604 show "${FUNCNAME[0]}" 605 606 start_time=$(get_time) 607 bucket_name="mc-test-bucket-$RANDOM" 608 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mb "${SERVER_ALIAS}/${bucket_name}" 609 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mirror "$DATA_DIR" "${SERVER_ALIAS}/${bucket_name}" 610 611 # find --older-than 1 day should be empty, so we compare with empty string. 612 diff -bB <(echo "") <("${MC_CMD[@]}" find "${SERVER_ALIAS}/${bucket_name}" --json --older-than 1d | jq -r .key | sed "s/${SERVER_ALIAS}\/${bucket_name}\///g") >/dev/null 2>&1 613 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "mirror and list differs" 614 615 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rb --force "${SERVER_ALIAS}/${bucket_name}" 616 617 log_success "$start_time" "${FUNCNAME[0]}" 618 } 619 620 ## Tests find command, should list. 621 function test_find() { 622 show "${FUNCNAME[0]}" 623 624 start_time=$(get_time) 625 bucket_name="mc-test-bucket-$RANDOM" 626 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mb "${SERVER_ALIAS}/${bucket_name}" 627 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mirror "$DATA_DIR" "${SERVER_ALIAS}/${bucket_name}" 628 629 diff -bB <(ls "$DATA_DIR") <("${MC_CMD[@]}" --json find "${SERVER_ALIAS}/${bucket_name}/" | jq -r .key | sed "s/${SERVER_ALIAS}\/${bucket_name}\///g") >/dev/null 2>&1 630 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "mirror and list differs" 631 632 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rb --force "${SERVER_ALIAS}/${bucket_name}" 633 634 log_success "$start_time" "${FUNCNAME[0]}" 635 } 636 637 function test_watch_object() 638 { 639 show "${FUNCNAME[0]}" 640 641 start_time=$(get_time) 642 bucket_name="mc-test-bucket-$RANDOM" 643 object_name="mc-test-object-$RANDOM" 644 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mb "${SERVER_ALIAS}/${bucket_name}" 645 646 # start a process to watch on bucket 647 "${MC_CMD[@]}" --json watch "${SERVER_ALIAS}/${bucket_name}" > "$WATCH_OUT_FILE" & 648 watch_cmd_pid=$! 649 sleep 1 650 651 ( assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${FILE_1_MB}" "${SERVER_ALIAS}/${bucket_name}/${object_name}" ) 652 rv=$? 653 if [ "$rv" -ne 0 ]; then 654 kill "$watch_cmd_pid" 655 exit "$rv" 656 fi 657 658 sleep 1 659 if ! jq -r .events.type "$WATCH_OUT_FILE" | grep -qi ObjectCreated; then 660 kill "$watch_cmd_pid" 661 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure 1 "ObjectCreated event not found" 662 fi 663 664 ( assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm "${SERVER_ALIAS}/${bucket_name}/${object_name}" ) 665 rv=$? 666 if [ "$rv" -ne 0 ]; then 667 kill "$watch_cmd_pid" 668 exit "$rv" 669 fi 670 671 sleep 1 672 if ! jq -r .events.type "$WATCH_OUT_FILE" | grep -qi ObjectRemoved; then 673 kill "$watch_cmd_pid" 674 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure 1 "ObjectRemoved event not found" 675 fi 676 677 kill "$watch_cmd_pid" 678 679 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rb --force "${SERVER_ALIAS}/${bucket_name}" 680 681 log_success "$start_time" "${FUNCNAME[0]}" 682 } 683 684 685 function test_config_host_add() 686 { 687 show "${FUNCNAME[0]}" 688 start_time=$(get_time) 689 690 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd alias set "${SERVER_ALIAS}1" "$ENDPOINT" "$ACCESS_KEY" "$SECRET_KEY" 691 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd alias list "${SERVER_ALIAS}1" 692 693 log_success "$start_time" "${FUNCNAME[0]}" 694 } 695 696 function test_config_host_add_error() 697 { 698 show "${FUNCNAME[0]}" 699 start_time=$(get_time) 700 701 out=$("${MC_CMD[@]}" --json alias set "${SERVER_ALIAS}1" "$ENDPOINT" "$ACCESS_KEY" "invalid-secret") 702 assert_failure "$start_time" "${FUNCNAME[0]}" show_on_success $? "adding host should fail" 703 got_code=$(echo "$out" | jq -r .error.cause.error.Code) 704 if [ "${got_code}" != "SignatureDoesNotMatch" ]; then 705 assert_failure "$start_time" "${FUNCNAME[0]}" show_on_failure 1 "incorrect error code ${got_code} returned by server" 706 fi 707 708 log_success "$start_time" "${FUNCNAME[0]}" 709 } 710 711 function test_put_object_with_sse() 712 { 713 show "${FUNCNAME[0]}" 714 start_time=$(get_time) 715 object_name="mc-test-object-$RANDOM" 716 cli_flag="${SERVER_ALIAS}/${BUCKET_NAME}=32byteslongsecretkeymustbegiven1" 717 # put encrypted object; then delete with correct secret key 718 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp --encrypt-key "${cli_flag}" "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 719 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm --encrypt-key "${cli_flag}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 720 log_success "$start_time" "${FUNCNAME[0]}" 721 } 722 723 function test_put_object_with_encoded_sse() 724 { 725 show "${FUNCNAME[0]}" 726 start_time=$(get_time) 727 object_name="mc-test-object-$RANDOM" 728 cli_flag="${SERVER_ALIAS}/${BUCKET_NAME}=MzJieXRlc2xvbmdzZWNyZWFiY2RlZmcJZ2l2ZW5uMjE=" 729 # put encrypted object; then delete with correct secret key 730 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp --encrypt-key "${cli_flag}" "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 731 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm --encrypt-key "${cli_flag}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 732 log_success "$start_time" "${FUNCNAME[0]}" 733 } 734 735 function test_put_object_with_sse_error() 736 { 737 show "${FUNCNAME[0]}" 738 start_time=$(get_time) 739 object_name="mc-test-object-$RANDOM" 740 cli_flag="${SERVER_ALIAS}/${BUCKET_NAME}=32byteslongsecretkeymustbegiven" 741 # put object with invalid encryption key; should fail 742 assert_failure "$start_time" "${FUNCNAME[0]}" mc_cmd cp --encrypt-key "${cli_flag}" "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 743 log_success "$start_time" "${FUNCNAME[0]}" 744 } 745 746 function test_cat_object_with_sse() 747 { 748 show "${FUNCNAME[0]}" 749 start_time=$(get_time) 750 object_name="mc-test-object-$RANDOM" 751 cli_flag="${SERVER_ALIAS}/${BUCKET_NAME}=32byteslongsecretkeymustbegiven1" 752 # put encrypted object; then cat object correct secret key 753 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp --encrypt-key "${cli_flag}" "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 754 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cat --encrypt-key "${cli_flag}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 755 log_success "$start_time" "${FUNCNAME[0]}" 756 } 757 758 function test_cat_object_with_sse_error() 759 { 760 show "${FUNCNAME[0]}" 761 start_time=$(get_time) 762 object_name="mc-test-object-$RANDOM" 763 cli_flag="${SERVER_ALIAS}/${BUCKET_NAME}=32byteslongsecretkeymustbegiven1" 764 # put encrypted object; then cat object with no secret key 765 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp --encrypt-key "${cli_flag}" "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 766 assert_failure "$start_time" "${FUNCNAME[0]}" mc_cmd cat "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 767 log_success "$start_time" "${FUNCNAME[0]}" 768 } 769 770 # Test "mc cp -r" command of a directory with and without a leading slash 771 function test_copy_directory() 772 { 773 show "${FUNCNAME[0]}" 774 775 random_dir="dir-$RANDOM-$RANDOM" 776 tmpdir="$(mktemp -d)" 777 778 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${random_dir}/object-name" 779 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "unable to upload an object" 780 781 # Copy a directory with a trailing slash 782 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp -r "${SERVER_ALIAS}/${BUCKET_NAME}/${random_dir}/" "${tmpdir}/" 783 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "unable to copy a directory with a trailing slash" 784 assert_success "$start_time" "${FUNCNAME[0]}" check_md5sum "$FILE_1_MB_MD5SUM" "${tmpdir}/object-name" 785 assert_success "$start_time" "${FUNCNAME[0]}" rm "${tmpdir}/object-name" 786 787 # Copy a directory without a trailing slash 788 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp -r "${SERVER_ALIAS}/${BUCKET_NAME}/${random_dir}" "${tmpdir}/" 789 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "unable to copy a directory without a trailing slash" 790 assert_success "$start_time" "${FUNCNAME[0]}" check_md5sum "$FILE_1_MB_MD5SUM" "${tmpdir}/${random_dir}/object-name" 791 792 # Cleanup 793 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm -r --force "${SERVER_ALIAS}/${BUCKET_NAME}/${random_dir}/" 794 assert_success "$start_time" "${FUNCNAME[0]}" rm -r "${tmpdir}" 795 796 log_success "$start_time" "${FUNCNAME[0]}" 797 } 798 799 # Test "mc cp -a" command to see if it preserves file system attributes 800 function test_copy_object_preserve_filesystem_attr() 801 { 802 show "${FUNCNAME[0]}" 803 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp -a "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 804 diff -bB <("${MC_CMD[@]}" --json stat "${FILE_1_MB}" | jq -r '.metadata."X-Amz-Meta-Mc-Attrs"') >/dev/null 2>&1 <("${MC_CMD[@]}" --json stat "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" | jq -r '.metadata."X-Amz-Meta-Mc-Attrs"') >/dev/null 2>&1 805 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "unable to put object with file system attribute" 806 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 807 log_success "$start_time" "${FUNCNAME[0]}" 808 } 809 810 # Test "mc mv" command 811 function test_mv_object() 812 { 813 show "${FUNCNAME[0]}" 814 815 random_dir="dir-$RANDOM-$RANDOM" 816 tmpdir="$(mktemp -d)" 817 818 # Test mv command locally 819 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "${FILE_1_MB}" "${tmpdir}/file.tmp" 820 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mv "${tmpdir}/file.tmp" "${tmpdir}/file" 821 assert_failure "$start_time" "${FUNCNAME[0]}" mc_cmd stat "${tmpdir}/file.tmp" 822 assert_success "$start_time" "${FUNCNAME[0]}" check_md5sum "$FILE_1_MB_MD5SUM" "${tmpdir}/file" 823 824 # Test mv command from filesystem to S3 825 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mv "${tmpdir}/file" "${SERVER_ALIAS}/${BUCKET_NAME}/${random_dir}/object-1" 826 assert_failure "$start_time" "${FUNCNAME[0]}" mc_cmd stat "${tmpdir}/file" 827 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd stat "${SERVER_ALIAS}/${BUCKET_NAME}/${random_dir}/object-1" 828 829 # Test mv command from S3 to S3 830 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mv "${SERVER_ALIAS}/${BUCKET_NAME}/${random_dir}/object-1" "${SERVER_ALIAS}/${BUCKET_NAME}/${random_dir}/object-2" 831 assert_failure "$start_time" "${FUNCNAME[0]}" mc_cmd stat "${SERVER_ALIAS}/${BUCKET_NAME}/${random_dir}/object-1" 832 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd stat "${SERVER_ALIAS}/${BUCKET_NAME}/${random_dir}/object-2" 833 834 # Test mv command from S3 to filesystem 835 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mv "${SERVER_ALIAS}/${BUCKET_NAME}/${random_dir}/object-2" "${tmpdir}/file" 836 assert_failure "$start_time" "${FUNCNAME[0]}" mc_cmd stat "${SERVER_ALIAS}/${BUCKET_NAME}/${random_dir}/object-2" 837 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd stat "${tmpdir}/file" 838 839 # Cleanup 840 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm -r --force "${SERVER_ALIAS}/${BUCKET_NAME}/${random_dir}/" 841 assert_success "$start_time" "${FUNCNAME[0]}" rm -r "${tmpdir}" 842 843 log_success "$start_time" "${FUNCNAME[0]}" 844 } 845 846 847 function test_copy_object_with_sse_rewrite() 848 { 849 # test server side copy and remove operation - target is unencrypted while source is encrypted 850 show "${FUNCNAME[0]}" 851 start_time=$(get_time) 852 prefix="prefix" 853 object_name="mc-test-object-$RANDOM" 854 855 cli_flag="${SERVER_ALIAS}/${BUCKET_NAME}/${prefix}=32byteslongsecretkeymustbegiven1" 856 # create encrypted object on server 857 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp --encrypt-key "${cli_flag}" "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${prefix}/${object_name}" 858 # now do a server side copy and store it unencrypted. 859 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp --encrypt-key "${cli_flag}" "${SERVER_ALIAS}/${BUCKET_NAME}/${prefix}/${object_name}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 860 # cat the unencrypted destination object. should return data without any error 861 "${MC_CMD[@]}" cat "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" >"${object_name}.downloaded" 862 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "unable to download object using 'mc cat'" 863 assert_success "$start_time" "${FUNCNAME[0]}" check_md5sum "$FILE_1_MB_MD5SUM" "${object_name}.downloaded" 864 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm "${object_name}.downloaded" 865 # mc rm on with multi-object delete, deletes encrypted object without encryption key. 866 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm --encrypt-key "${cli_flag}" "${SERVER_ALIAS}/${BUCKET_NAME}/${prefix}/${object_name}" 867 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 868 869 log_success "$start_time" "${FUNCNAME[0]}" 870 } 871 872 function test_copy_object_with_sse_dest() 873 { 874 # test server side copy and remove operation - target is encrypted with different key 875 show "${FUNCNAME[0]}" 876 start_time=$(get_time) 877 prefix="prefix" 878 object_name="mc-test-object-$RANDOM" 879 880 cli_flag1="${SERVER_ALIAS}/${BUCKET_NAME}/${prefix}=32byteslongsecretkeymustbegiven1" 881 cli_flag2="${SERVER_ALIAS}/${BUCKET_NAME}=32byteslongsecretkeymustbegiven2" 882 883 # create encrypted object on server 884 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp --encrypt-key "${cli_flag1}" "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${prefix}/${object_name}" 885 # now do a server side copy and store it eith different encryption key. 886 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp --encrypt-key "${cli_flag1},${cli_flag2}" "${SERVER_ALIAS}/${BUCKET_NAME}/${prefix}/${object_name}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 887 # cat the destination object with the new key. should return data without any error 888 "${MC_CMD[@]}" cat --encrypt-key "${cli_flag2}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" > "${object_name}.downloaded" 889 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "unable to download object using 'mc cat'" 890 assert_success "$start_time" "${FUNCNAME[0]}" check_md5sum "$FILE_1_MB_MD5SUM" "${object_name}.downloaded" 891 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm "${object_name}.downloaded" 892 # mc rm on src object with first encryption key should pass 893 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm --encrypt-key "${cli_flag1}" "${SERVER_ALIAS}/${BUCKET_NAME}/${prefix}/${object_name}" 894 # mc rm on encrypted destination object with second encryption key should pass 895 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm --encrypt-key "${cli_flag2}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 896 897 log_success "$start_time" "${FUNCNAME[0]}" 898 } 899 900 function test_sse_key_rotation() 901 { 902 # test server side copy and remove operation - target is encrypted with different key 903 show "${FUNCNAME[0]}" 904 start_time=$(get_time) 905 prefix="prefix" 906 object_name="mc-test-object-$RANDOM" 907 old_key="32byteslongsecretkeymustbegiven1" 908 new_key="32byteslongsecretkeymustbegiven2" 909 cli_flag1="${SERVER_ALIAS}/${BUCKET_NAME}/${prefix}=${old_key}" 910 cli_flag2="${SERVER_ALIAS_TLS}/${BUCKET_NAME}=${new_key}" 911 912 # create encrypted object on server 913 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp --encrypt-key "${cli_flag1}" "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${prefix}/${object_name}" 914 # now do a server side copy on same object and do a key rotation 915 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp --encrypt-key "${cli_flag1},${cli_flag2}" "${SERVER_ALIAS}/${BUCKET_NAME}/${prefix}/${object_name}" "${SERVER_ALIAS_TLS}/${BUCKET_NAME}/${object_name}" 916 # cat the object with the new key. should return data without any error 917 "${MC_CMD[@]}" cat --encrypt-key "${cli_flag2}" "${SERVER_ALIAS_TLS}/${BUCKET_NAME}/${object_name}" > "${object_name}.downloaded" 918 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "unable to download object using 'mc cat'" 919 assert_success "$start_time" "${FUNCNAME[0]}" check_md5sum "$FILE_1_MB_MD5SUM" "${object_name}.downloaded" 920 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm "${object_name}.downloaded" 921 # mc rm on encrypted object with succeed anyways, without encrypted keys. 922 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm "${SERVER_ALIAS_TLS}/${BUCKET_NAME}/${object_name}" 923 924 log_success "$start_time" "${FUNCNAME[0]}" 925 } 926 927 function test_mirror_with_sse() 928 { 929 # test if mirror operation works with encrypted objects 930 show "${FUNCNAME[0]}" 931 932 start_time=$(get_time) 933 bucket_name="mc-test-bucket-$RANDOM" 934 cli_flag="${SERVER_ALIAS}/${bucket_name}=32byteslongsecretkeymustbegiven1" 935 936 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mb "${SERVER_ALIAS}/${bucket_name}" 937 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd mirror --encrypt-key "${cli_flag}" "$DATA_DIR" "${SERVER_ALIAS}/${bucket_name}" 938 diff -bB <(ls "$DATA_DIR") <("${MC_CMD[@]}" --json ls "${SERVER_ALIAS}/${bucket_name}/" | jq -r .key) >/dev/null 2>&1 939 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure $? "mirror and list differs" 940 # Remove the test bucket with its contents 941 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rb --force "${SERVER_ALIAS}/${bucket_name}" 942 943 log_success "$start_time" "${FUNCNAME[0]}" 944 } 945 946 function test_rm_object_with_sse() 947 { 948 show "${FUNCNAME[0]}" 949 950 # test whether remove fails for encrypted object if secret key not provided. 951 start_time=$(get_time) 952 object_name="mc-test-object-$RANDOM" 953 cli_flag="${SERVER_ALIAS}/${BUCKET_NAME}=32byteslongsecretkeymustbegiven1" 954 955 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp --encrypt-key "${cli_flag}" "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 956 # rm will not fail even if the encryption keys are not provided, since mc rm uses multi-object delete. 957 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 958 959 log_success "$start_time" "${FUNCNAME[0]}" 960 } 961 962 function test_get_object_with_sse() 963 { 964 show "${FUNCNAME[0]}" 965 966 start_time=$(get_time) 967 object_name="mc-test-object-$RANDOM" 968 cli_flag="${SERVER_ALIAS}/${BUCKET_NAME}=32byteslongsecretkeymustbegiven1" 969 970 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp --encrypt-key "${cli_flag}" "${FILE_1_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 971 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp --encrypt-key "${cli_flag}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" "${object_name}.downloaded" 972 assert_success "$start_time" "${FUNCNAME[0]}" check_md5sum "$FILE_1_MB_MD5SUM" "${object_name}.downloaded" 973 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm --encrypt-key "${cli_flag}" "${object_name}.downloaded" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 974 975 log_success "$start_time" "${FUNCNAME[0]}" 976 } 977 978 function test_put_object_multipart_sse() 979 { 980 show "${FUNCNAME[0]}" 981 982 start_time=$(get_time) 983 object_name="mc-test-object-$RANDOM" 984 cli_flag="${SERVER_ALIAS}/${BUCKET_NAME}=32byteslongsecretkeymustbegiven1" 985 986 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp --encrypt-key "${cli_flag}" "${FILE_65_MB}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 987 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm --encrypt-key "${cli_flag}" "${SERVER_ALIAS}/${BUCKET_NAME}/${object_name}" 988 989 log_success "$start_time" "${FUNCNAME[0]}" 990 } 991 992 function test_admin_users() 993 { 994 show "${FUNCNAME[0]}" 995 996 start_time=$(get_time) 997 998 # create a user 999 username=foo 1000 password=foobar12345 1001 test_alias="aliasx" 1002 1003 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd admin user add "$SERVER_ALIAS" "$username" "$password" 1004 1005 # check that user appears in the user list 1006 "${MC_CMD[@]}" --json admin user list "${SERVER_ALIAS}" | jq -r '.accessKey' | grep --quiet "^${username}$" 1007 rv=$? 1008 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure ${rv} "user ${username} did NOT appear in the list of users returned by server" 1009 1010 # setup temporary alias to make requests as the created user. 1011 scheme="https" 1012 if [ "$ENABLE_HTTPS" != "1" ]; then 1013 scheme="http" 1014 fi 1015 object1_name="mc-test-object-$RANDOM" 1016 object2_name="mc-test-object-$RANDOM" 1017 1018 # Adding an alias for the $test_alias 1019 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd alias set $test_alias "${scheme}://${SERVER_ENDPOINT}" ${username} ${password} 1020 1021 # check that alias appears in the alias list 1022 "${MC_CMD[@]}" --json alias list | jq -r '.alias' | grep --quiet "^${test_alias}$" 1023 rv=$? 1024 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure ${rv} "alias ${test_alias} did NOT appear in the list of aliases returned by server" 1025 1026 # check that the user can write objects with readwrite policy 1027 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd admin policy attach "$SERVER_ALIAS" readwrite --user="${username}" 1028 1029 # Validate that the correct policy has been added to the user 1030 "${MC_CMD[@]}" --json admin user list "${SERVER_ALIAS}" | jq -r '.policyName' | grep --quiet "^readwrite$" 1031 rv=$? 1032 assert_success "$start_time" "${FUNCNAME[0]}" show_on_failure ${rv} "user ${username} did NOT have the readwrite policy attached" 1033 1034 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "$FILE_1_MB" "${test_alias}/${BUCKET_NAME}/${object1_name}" 1035 1036 # check that the user cannot write objects with readonly policy 1037 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd admin policy detach "$SERVER_ALIAS" readwrite --user="${username}" 1038 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd admin policy attach "$SERVER_ALIAS" readonly --user="${username}" 1039 assert_failure "$start_time" "${FUNCNAME[0]}" mc_cmd cp "$FILE_1_MB" "${test_alias}/${BUCKET_NAME}/${object2_name}" 1040 1041 # check that the user can read with readonly policy 1042 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cat "${test_alias}/${BUCKET_NAME}/${object1_name}" 1043 1044 # check that user can delete with readwrite policy 1045 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd admin policy attach "$SERVER_ALIAS" readwrite --user="${username}" 1046 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd rm "${test_alias}/${BUCKET_NAME}/${object1_name}" 1047 1048 # check that user cannot perform admin actions with readwrite policy 1049 assert_failure "$start_time" "${FUNCNAME[0]}" mc_cmd admin info $test_alias 1050 1051 # create object1_name for subsequent tests. 1052 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cp "$FILE_1_MB" "${test_alias}/${BUCKET_NAME}/${object1_name}" 1053 1054 # check that user can be disabled 1055 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd admin user disable "$SERVER_ALIAS" "$username" 1056 1057 # check that disabled cannot perform any action 1058 assert_failure "$start_time" "${FUNCNAME[0]}" mc_cmd cat "${test_alias}/${BUCKET_NAME}/${object1_name}" 1059 1060 # check that user can be enabled and can then perform an allowed action 1061 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd admin user enable "$SERVER_ALIAS" "$username" 1062 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd cat "${test_alias}/${BUCKET_NAME}/${object1_name}" 1063 1064 # check that user can be removed, and then is no longer available 1065 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd admin user remove "$SERVER_ALIAS" "$username" 1066 assert_failure "$start_time" "${FUNCNAME[0]}" mc_cmd cat "${test_alias}/${BUCKET_NAME}/${object1_name}" 1067 1068 log_success "$start_time" "${FUNCNAME[0]}" 1069 } 1070 1071 function run_test() 1072 { 1073 test_make_bucket 1074 test_make_bucket_error 1075 test_rb 1076 1077 setup 1078 test_list_dir 1079 test_put_object 1080 test_put_object_error 1081 test_put_object_0byte 1082 test_put_object_with_storage_class 1083 test_put_object_with_storage_class_error 1084 test_put_object_with_metadata 1085 test_put_object_multipart 1086 test_get_object 1087 test_get_object_multipart 1088 test_od_object 1089 test_mv_object 1090 test_presigned_post_policy_error 1091 test_presigned_put_object 1092 test_presigned_get_object 1093 test_cat_object 1094 test_cat_stdin 1095 test_copy_directory 1096 test_mirror_list_objects 1097 test_mirror_list_objects_storage_class 1098 test_copy_object_preserve_filesystem_attr 1099 test_find 1100 test_find_empty 1101 if [ -z "$MINT_MODE" ]; then 1102 test_watch_object 1103 fi 1104 1105 if [ "$ENABLE_HTTPS" == "1" ]; then 1106 test_put_object_with_sse 1107 test_put_object_with_encoded_sse 1108 test_put_object_with_sse_error 1109 test_put_object_multipart_sse 1110 test_get_object_with_sse 1111 test_cat_object_with_sse 1112 test_cat_object_with_sse_error 1113 test_copy_object_with_sse_rewrite 1114 test_copy_object_with_sse_dest 1115 test_sse_key_rotation 1116 test_mirror_with_sse 1117 test_rm_object_with_sse 1118 fi 1119 1120 test_config_host_add 1121 test_config_host_add_error 1122 test_admin_users 1123 1124 teardown 1125 } 1126 1127 function __init__() 1128 { 1129 set -e 1130 if [ -n "$DEBUG" ]; then 1131 set -x 1132 fi 1133 1134 # For Mint, setup is already done. For others, setup the environment 1135 if [ -z "$MINT_MODE" ]; then 1136 mkdir -p "$WORK_DIR" 1137 mkdir -p "$DATA_DIR" 1138 1139 # If mc executable binary is not available in current directory, use it in the path. 1140 if [ ! -x "$MC" ]; then 1141 if ! MC=$(which mc 2>/dev/null); then 1142 echo "'mc' executable binary not found in current directory and in path" 1143 exit 1 1144 fi 1145 fi 1146 fi 1147 1148 if [ ! -x "$MC" ]; then 1149 echo "$MC executable binary not found" 1150 exit 1 1151 fi 1152 1153 mkdir -p "$MC_CONFIG_DIR" 1154 MC_CMD=( "${MC}" --config-dir "$MC_CONFIG_DIR" --quiet --no-color ) 1155 1156 if [ ! -e "$FILE_0_B" ]; then 1157 touch "$FILE_0_B" 1158 fi 1159 1160 if [ ! -e "$FILE_1_MB" ]; then 1161 base64 -i /dev/urandom | head -c 1048576 >"$FILE_1_MB" 1162 fi 1163 1164 if [ ! -e "$FILE_65_MB" ]; then 1165 base64 -i /dev/urandom | head -c 68157440 >"$FILE_65_MB" 1166 fi 1167 1168 set -E 1169 set -o pipefail 1170 1171 FILE_0_B_MD5SUM="$(get_md5sum "$FILE_0_B")" 1172 if [ $? -ne 0 ]; then 1173 echo "unable to get md5sum of $FILE_0_B" 1174 exit 1 1175 fi 1176 1177 FILE_1_MB_MD5SUM="$(get_md5sum "$FILE_1_MB")" 1178 if [ $? -ne 0 ]; then 1179 echo "unable to get md5sum of $FILE_1_MB" 1180 exit 1 1181 fi 1182 1183 FILE_65_MB_MD5SUM="$(get_md5sum "$FILE_65_MB")" 1184 if [ $? -ne 0 ]; then 1185 echo "unable to get md5sum of $FILE_65_MB" 1186 exit 1 1187 fi 1188 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd alias set "${SERVER_ALIAS}" "$ENDPOINT" "$ACCESS_KEY" "$SECRET_KEY" 1189 assert_success "$start_time" "${FUNCNAME[0]}" mc_cmd alias set "${SERVER_ALIAS_TLS}" "$ENDPOINT" "$ACCESS_KEY" "$SECRET_KEY" 1190 1191 set +e 1192 } 1193 1194 function validate_dependencies() { 1195 jqVersion=$(jq --version) 1196 if [[ $jqVersion == *"jq"* ]]; then 1197 echo "Dependency validation complete" 1198 else 1199 echo "jq is missing, please install: 'sudo apt install jq'" 1200 exit 1 1201 fi 1202 } 1203 1204 function main() 1205 { 1206 validate_dependencies 1207 1208 ( run_test ) 1209 rv=$? 1210 1211 rm -fr "$MC_CONFIG_DIR" "$WATCH_OUT_FILE" 1212 if [ -z "$MINT_MODE" ]; then 1213 rm -fr "$WORK_DIR" "$DATA_DIR" 1214 fi 1215 1216 exit "$rv" 1217 } 1218 1219 __init__ "$@" 1220 main "$@"