run.sh 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #!/bin/bash
  2. set -e
  3. image="$1"
  4. haveSeccomp=
  5. if docker info --format '{{ join .SecurityOptions "\n" }}' 2>/dev/null |tac|tac| grep -q seccomp; then
  6. haveSeccomp=1
  7. # get docker default seccomp profile
  8. seccomp="$(wget -q -O - 'https://raw.githubusercontent.com/docker/docker/v17.03.1-ce/profiles/seccomp/default.json')"
  9. # make container with jq since it is not guaranteed on the host
  10. jqImage='librarytest/mongo-basics-jq:alpine'
  11. docker build -t "$jqImage" - > /dev/null <<-'EOF'
  12. FROM alpine:3.9
  13. RUN apk add --no-cache jq
  14. ENTRYPOINT ["jq"]
  15. EOF
  16. # need set_mempolicy syscall to be able to do numactl for mongodb
  17. # if "set_mempolicy" is not in the always allowed list, add it
  18. extraSeccomp="$(echo "$seccomp" | docker run -i --rm "$jqImage" --tab '
  19. .syscalls[] |= if (
  20. .action == "SCMP_ACT_ALLOW"
  21. and .args == []
  22. and .comment == ""
  23. and .includes == {}
  24. and .excludes == {}
  25. ) then (
  26. if ( .names | index("set_mempolicy") ) > 0 then
  27. .
  28. else (
  29. .names |= . + ["set_mempolicy"]
  30. ) end
  31. )
  32. else
  33. .
  34. end
  35. ')"
  36. else
  37. echo >&2 'warning: the current Docker daemon does not appear to support seccomp'
  38. fi
  39. docker_run_seccomp() {
  40. if [ "$haveSeccomp" ]; then
  41. docker run --security-opt seccomp=<(echo "$extraSeccomp") "$@"
  42. else
  43. docker run "$@"
  44. fi
  45. }
  46. cname="mongo-container-$RANDOM-$RANDOM"
  47. mongodRunArgs=( -d --name "$cname" )
  48. mongodCmdArgs=()
  49. mongoArgs=( --host mongo )
  50. testDir="$(readlink -f "$(dirname "$BASH_SOURCE")")"
  51. testName="$(basename "$testDir")" # "mongo-basics" or "mongo-auth-basics" or "mongo-tls-auth"
  52. if [[ "$testName" == *auth* ]]; then
  53. rootUser="root-$RANDOM"
  54. rootPass="root-$RANDOM-$RANDOM-password"
  55. mongodRunArgs+=(
  56. -e MONGO_INITDB_ROOT_USERNAME="$rootUser"
  57. -e MONGO_INITDB_ROOT_PASSWORD="$rootPass"
  58. )
  59. mongoArgs+=(
  60. --username="$rootUser"
  61. --password="$rootPass"
  62. --authenticationDatabase='admin'
  63. )
  64. fi
  65. if [[ "$testName" == *tls* ]]; then
  66. tlsImage="$("$testDir/../image-name.sh" librarytest/mongo-tls "$image")"
  67. "$testDir/../docker-build.sh" "$testDir" "$tlsImage" <<-EOD
  68. FROM alpine:3.10 AS certs
  69. RUN apk add --no-cache openssl
  70. RUN set -eux; \
  71. mkdir /certs; \
  72. openssl genrsa -out /certs/ca-private.key 8192; \
  73. openssl req -new -x509 \
  74. -key /certs/ca-private.key \
  75. -out /certs/ca.crt \
  76. -days $(( 365 * 30 )) \
  77. -subj '/CN=lolca'; \
  78. openssl genrsa -out /certs/private.key 4096; \
  79. openssl req -new -key /certs/private.key \
  80. -out /certs/cert.csr -subj '/CN=mongo'; \
  81. openssl x509 -req -in /certs/cert.csr \
  82. -CA /certs/ca.crt -CAkey /certs/ca-private.key -CAcreateserial \
  83. -out /certs/cert.crt -days $(( 365 * 30 )); \
  84. openssl verify -CAfile /certs/ca.crt /certs/cert.crt
  85. FROM $image
  86. # gotta be :0 because percona's mongo doesn't have a mongodb group and estesp slayed tianon with https://github.com/moby/moby/pull/34263/files#diff-f157a3a45b3e5d85aadff73bff1f5a7cR170-R171
  87. COPY --from=certs --chown=mongodb:0 /certs /certs
  88. RUN cat /certs/cert.crt /certs/private.key > /certs/both.pem # yeah, what
  89. EOD
  90. image="$tlsImage"
  91. mongodRunArgs+=(
  92. --hostname mongo
  93. )
  94. # test for 4.2+ (where "s/ssl/tls/" was applied to all related options/flags)
  95. # see https://docs.mongodb.com/manual/tutorial/configure-ssl/#procedures-using-net-ssl-settings
  96. if docker run --rm "$image" mongod --help 2>&1 | grep -q -- ' --tlsMode '; then
  97. mongodCmdArgs+=(
  98. --tlsMode requireTLS
  99. --tlsCertificateKeyFile /certs/both.pem
  100. )
  101. mongoArgs+=(
  102. --tls
  103. --tlsCAFile /certs/ca.crt
  104. )
  105. else
  106. mongodCmdArgs+=(
  107. --sslMode requireSSL
  108. --sslPEMKeyFile /certs/both.pem
  109. )
  110. mongoArgs+=(
  111. --ssl
  112. --sslCAFile /certs/ca.crt
  113. )
  114. fi
  115. fi
  116. cid="$(docker_run_seccomp "${mongodRunArgs[@]}" "$image" "${mongodCmdArgs[@]}")"
  117. trap "docker rm -vf $cid > /dev/null" EXIT
  118. mongo() {
  119. docker_run_seccomp --rm -i --link "$cname":mongo "$image" mongo "${mongoArgs[@]}" "$@"
  120. }
  121. mongo_eval() {
  122. mongo --quiet --eval "$@"
  123. }
  124. . "$testDir/../../retry.sh" "mongo_eval 'quit(db.stats().ok ? 0 : 1);'"
  125. if false; then
  126. tries=10
  127. while ! mongo_eval 'quit(db.stats().ok ? 0 : 1);' &> /dev/null; do
  128. (( tries-- ))
  129. if [ $tries -le 0 ]; then
  130. echo >&2 'mongod failed to accept connections in a reasonable amount of time!'
  131. ( set -x && docker logs "$cid" ) >&2 || true
  132. mongo --eval 'db.stats();' # to hopefully get a useful error message
  133. false
  134. fi
  135. echo >&2 -n .
  136. sleep 2
  137. done
  138. fi
  139. [ "$(mongo_eval 'db.test.count();')" = 0 ]
  140. mongo_eval 'db.test.save({ _id: 1, a: 2, b: 3, c: "hello" });' > /dev/null
  141. [ "$(mongo_eval 'db.test.count();')" = 1 ]
  142. mongo_eval 'db.test.save({ _id: 1, a: 3, b: 4, c: "hello" });' > /dev/null
  143. [ "$(mongo_eval 'db.test.count();')" = 1 ]
  144. [ "$(mongo_eval 'db.test.findOne().a;')" = 3 ]
  145. [ "$(mongo_eval 'db.test2.count();')" = 0 ]
  146. mongo_eval 'db.test2.save({ _id: "abc" });' > /dev/null
  147. [ "$(mongo_eval 'db.test2.count();')" = 1 ]
  148. [ "$(mongo_eval 'db.test.count();')" = 1 ]
  149. mongo_eval 'db.test2.drop();' > /dev/null
  150. [ "$(mongo_eval 'db.test2.count();')" = 0 ]
  151. [ "$(mongo_eval 'db.test.count();')" = 1 ]
  152. [ "$(mongo_eval 'db.test.count();' database-that-does-not-exist)" = 0 ]
  153. mongo_eval 'db.dropDatabase();' > /dev/null
  154. [ "$(mongo_eval 'db.test.count();')" = 0 ]