diff options
author | David Golden <xdg@xdg.me> | 2018-07-13 14:30:21 -0400 |
---|---|---|
committer | David Golden <xdg@xdg.me> | 2018-07-13 16:02:52 -0400 |
commit | daa559be8821b7c06ca9ca6f3638a1842348ef8d (patch) | |
tree | db7ee142106ef606094d6405f86cf82f7777c802 | |
parent | cf1f02c116a9f28b97bc6c41148446342349785c (diff) | |
download | mongo-daa559be8821b7c06ca9ca6f3638a1842348ef8d.tar.gz |
Import tools: 5f036603357e3d910e4d765369261fd0b577dd59 from branch v4.1
ref: 37adadadd5..5f03660335
for: 4.1.1
TOOLS-1709 Set build version and git revision using -ldflags
TOOLS-1970 Add replay-dist task to evergreen wherever we think it will succeed
TOOLS-1991 Build tools with Go 1.10.1
TOOLS-2060 Support mongoreplay playback using ssl
TOOLS-2067 sslFIPSMode doesn't error when unavailable in openssl
TOOLS-2075 mongoreplay always replays to secondary
26 files changed, 1286 insertions, 99 deletions
diff --git a/src/mongo/gotools/build.sh b/src/mongo/gotools/build.sh index 9ca53c4f429..6511d7af558 100755 --- a/src/mongo/gotools/build.sh +++ b/src/mongo/gotools/build.sh @@ -10,9 +10,10 @@ fi SCRIPT_DIR="$(cd "$(dirname ${BASH_SOURCE[0]})" && pwd)" cd $SCRIPT_DIR -sed -i.bak -e "s/built-without-version-string/$(git describe)/" \ - -e "s/built-without-git-spec/$(git rev-parse HEAD)/" \ - common/options/options.go +VersionStr="$(git describe)" +Gitspec="$(git rev-parse HEAD)" +importpath="github.com/mongodb/mongo-tools/common/options" +ldflags="-X ${importpath}.VersionStr=${VersionStr} -X ${importpath}.Gitspec=${Gitspec}" # remove stale packages rm -rf vendor/pkg @@ -23,7 +24,7 @@ mkdir -p bin ec=0 for i in bsondump mongostat mongofiles mongoexport mongoimport mongorestore mongodump mongotop mongoreplay; do echo "Building ${i}..." - go build -o "bin/$i" -tags "$tags" "$i/main/$i.go" || { echo "Error building $i"; ec=1; break; } + go build -o "bin/$i" -ldflags "$ldflags" -tags "$tags" "$i/main/$i.go" || { echo "Error building $i"; ec=1; break; } ./bin/$i --version | head -1 done @@ -31,5 +32,4 @@ if [ -t /dev/stdin ]; then stty sane fi -mv -f common/options/options.go.bak common/options/options.go exit $ec diff --git a/src/mongo/gotools/common.yml b/src/mongo/gotools/common.yml index fe419d94608..b54f943cefa 100644 --- a/src/mongo/gotools/common.yml +++ b/src/mongo/gotools/common.yml @@ -29,20 +29,20 @@ mongo_tools_variables: - name: qa-dump-restore-archiving - name: qa-dump-restore-archiving-3.2 - name: unit -# disabled until BUILD-2273 is done -# - name: replay-dist -# - name: replay-sanity_check -# - name: replay-go_test -# - name: replay-auth_test -# - name: replay-sharded_test -# - name: replay-repl_test -# - name: replay-replay_test + - name: replay-dist + - name: replay-sanity_check + - name: replay-go_test + - name: replay-auth_test + - name: replay-sharded_test + - name: replay-repl_test + - name: replay-replay_test macos_1012_ssl_task_list: &macos_1012_ssl_tasks - name: dist - name: qa-tests-4.0 - name: qa-tests-unstable - name: native-cert-ssl - name: unit + - name: replay-dist ubuntu1404_x86_64_task_list: &ubuntu1404_x86_64_tasks - name: db - name: dist @@ -77,6 +77,7 @@ mongo_tools_variables: - name: qa-tests-4.0 - name: qa-tests-unstable - name: native-cert-ssl + - name: replay-dist ubuntu1404_x86_64_enterprise_task_list: &ubuntu1404_x86_64_enterprise_tasks - name: db - name: dist @@ -193,14 +194,13 @@ mongo_tools_variables: - name: qa-tests-4.0 - name: qa-tests-unstable - name: native-cert-ssl -# disabled until BUILD-2273 is done -# - name: replay-dist -# - name: replay-sanity_check -# - name: replay-go_test -# - name: replay-auth_test -# - name: replay-sharded_test -# - name: replay-repl_test -# - name: replay-replay_test + - name: replay-dist + - name: replay-sanity_check + - name: replay-go_test + - name: replay-auth_test + - name: replay-sharded_test + - name: replay-repl_test + - name: replay-replay_test rhel67_s390x_enterprise_task_list: &rhel67_s390x_enterprise_tasks - name: db - name: dist @@ -214,14 +214,13 @@ mongo_tools_variables: - name: qa-tests-4.0 - name: qa-tests-unstable - name: native-cert-ssl -# disabled until BUILD-2273 is done -# - name: replay-dist -# - name: replay-sanity_check -# - name: replay-go_test -# - name: replay-auth_test -# - name: replay-sharded_test -# - name: replay-repl_test -# - name: replay-replay_test + - name: replay-dist + - name: replay-sanity_check + - name: replay-go_test + - name: replay-auth_test + - name: replay-sharded_test + - name: replay-repl_test + - name: replay-replay_test ubuntu1604_arm64_ssl_task_list: &ubuntu1604_arm64_ssl_tasks - name: db - name: dist @@ -234,6 +233,7 @@ mongo_tools_variables: - name: qa-tests-4.0 - name: qa-tests-unstable - name: native-cert-ssl + - name: replay-dist ## Common mongodb arguments @@ -270,7 +270,7 @@ functions: chmod +x bin/* mv bin/* ${test_path}/ cd ${test_path} - python buildscripts/smoke.py ${smoke_use_ssl} --nopreallocj --with-cleanbb --mongod ./mongod --mongo ./mongo --report-file ../../report.json --continue-on-failure --buildlogger-builder MCI_${build_variant} --buildlogger-buildnum ${builder_num|} --buildlogger-credentials ./mci.buildlogger --buildlogger-phase ${task_name}_${execution} ${smoke_args} tool + python buildscripts/smoke.py ${smoke_use_ssl} --with-cleanbb --mongod ./mongod --mongo ./mongo --report-file ../../report.json --continue-on-failure --buildlogger-builder MCI_${build_variant} --buildlogger-buildnum ${builder_num|} --buildlogger-credentials ./mci.buildlogger --buildlogger-phase ${task_name}_${execution} ${smoke_args} tool "run qa-tests": command: shell.exec @@ -1638,55 +1638,59 @@ buildvariants: ####################################### - name: amazonlinux64 - display_name: Amazon Linux 64 (Go 1.8) + display_name: Amazon Linux 64 (Go 1.10) run_on: - linux-64-amzn-test expansions: - gorootvars: 'PATH="/opt/go1.8/go/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/go1.8/go' + gorootvars: 'PATH="/opt/golang/go1.10/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/golang/go1.10' build_tags: "sasl ssl" tasks: - name: dist + - name: replay-dist - name: amazon2 - display_name: Amazon Linux 64 v2 (Go 1.8) + display_name: Amazon Linux 64 v2 (Go 1.10) run_on: - amazon2-test expansions: - gorootvars: 'PATH="/opt/go1.8/go/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/go1.8/go' + gorootvars: 'PATH="/opt/golang/go1.10/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/golang/go1.10' build_tags: "sasl ssl" tasks: - name: dist + - name: replay-dist ####################################### # Debian x86_64 Buildvariants # ####################################### - name: debian81 - display_name: Debian 8.1 (Go 1.8) + display_name: Debian 8.1 (Go 1.10) run_on: - debian81-test expansions: - gorootvars: 'PATH="/opt/go1.8/go/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/go1.8/go' + gorootvars: 'PATH="/opt/golang/go1.10/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/golang/go1.10' build_tags: "sasl ssl" tasks: - name: dist + - name: replay-dist - name: debian92 - display_name: Debian 9.2 (Go 1.8) + display_name: Debian 9.2 (Go 1.10) run_on: - debian92-test expansions: - gorootvars: 'PATH="/opt/go1.8/go/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/go1.8/go' + gorootvars: 'PATH="/opt/golang/go1.10/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/golang/go1.10' build_tags: "sasl ssl" tasks: - name: dist + - name: replay-dist ####################################### # macOS Buildvariant # ####################################### - name: macOS-1012 - display_name: MacOS 10.12 (Go 1.8) + display_name: MacOS 10.12 (Go 1.10) run_on: - macos-1012 expansions: @@ -1696,11 +1700,11 @@ buildvariants: mongo_target: "osx-ssl" arch: "osx/x86_64" excludes: requires_many_files - gorootvars: 'PATH="/usr/local/go1.8/go/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/usr/local/go1.8/go' + gorootvars: 'PATH="/opt/golang/go1.10/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/golang/go1.10' tasks: *macos_1012_tasks - name: macOS-1012-ssl - display_name: MacOS 10.12 SSL (Go 1.8) + display_name: MacOS 10.12 SSL (Go 1.10) run_on: - macos-1012 expansions: @@ -1711,7 +1715,7 @@ buildvariants: arch: "osx/x86_64" build_tags: "ssl openssl_pre_1.0" excludes: requires_many_files - gorootvars: 'PATH="/usr/local/go1.8/go/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/usr/local/go1.8/go' + gorootvars: 'PATH="/opt/golang/go1.10/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/golang/go1.10' tasks: *macos_1012_ssl_tasks ####################################### @@ -1719,45 +1723,48 @@ buildvariants: ####################################### - name: rhel62 - display_name: RHEL 6.2 (Go 1.8) + display_name: RHEL 6.2 (Go 1.10) run_on: - rhel62-test expansions: - gorootvars: 'PATH="/opt/go1.8/go/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/go1.8/go' + gorootvars: 'PATH="/opt/golang/go1.10/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/golang/go1.10' build_tags: "sasl ssl" tasks: - name: dist + - name: replay-dist - name: rhel70 - display_name: RHEL 7.0 (Go 1.8) + display_name: RHEL 7.0 (Go 1.10) run_on: - rhel70 expansions: - gorootvars: 'PATH="/opt/go1.8/go/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/go1.8/go' + gorootvars: 'PATH="/opt/golang/go1.10/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/golang/go1.10' build_tags: "sasl ssl" tasks: - name: dist + - name: replay-dist ####################################### # SUSE x86_64 Buildvariants # ####################################### - name: suse12 - display_name: SUSE 12 (Go 1.8) + display_name: SUSE 12 (Go 1.10) run_on: - suse12-test expansions: - gorootvars: 'PATH="/opt/go1.8/go/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/go1.8/go' + gorootvars: 'PATH="/opt/golang/go1.10/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/golang/go1.10' build_tags: "sasl ssl" tasks: - name: dist + - name: replay-dist ####################################### # Ubuntu x86_64 Buildvariants # ####################################### - name: ubuntu1404 - display_name: Ubuntu 14.04 (Go 1.8) + display_name: Ubuntu 14.04 (Go 1.10) run_on: - ubuntu1404-test expansions: @@ -1765,7 +1772,7 @@ buildvariants: <<: *mongo_default_startup_args mongo_os: "ubuntu1404" mongo_edition: "targeted" - gorootvars: 'PATH="/opt/go1.8/go/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/go1.8/go' + gorootvars: 'PATH="/opt/golang/go1.10/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/golang/go1.10' build_tags: "sasl ssl" arch: "linux/x86_64" integration_test_args: integration @@ -1773,7 +1780,7 @@ buildvariants: tasks: *ubuntu1404_x86_64_tasks - name: ubuntu1404-ssl - display_name: Ubuntu 14.04 SSL (Go 1.8) + display_name: Ubuntu 14.04 SSL (Go 1.10) run_on: - ubuntu1404-test expansions: @@ -1781,7 +1788,7 @@ buildvariants: <<: *mongo_ssl_startup_args mongo_os: "ubuntu1404" mongo_edition: "enterprise" - gorootvars: 'PATH="/opt/go1.8/go/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/go1.8/go' + gorootvars: 'PATH="/opt/golang/go1.10/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/golang/go1.10' build_tags: "sasl ssl" edition: ssl arch: "linux/x86_64" @@ -1792,7 +1799,7 @@ buildvariants: tasks: *ubuntu1404_x86_64_ssl_tasks - name: ubuntu1404-enterprise - display_name: Ubuntu 14.04 Enterprise (Go 1.8) + display_name: Ubuntu 14.04 Enterprise (Go 1.10) run_on: - ubuntu1404-test expansions: @@ -1800,7 +1807,7 @@ buildvariants: <<: *mongo_default_startup_args mongo_os: "ubuntu1404" mongo_edition: "enterprise" - gorootvars: 'PATH="/opt/go1.8/go/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/go1.8/go' + gorootvars: 'PATH="/opt/golang/go1.10/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/golang/go1.10' build_tags: "ssl sasl" smoke_use_ssl: --use-ssl resmoke_use_ssl: _ssl @@ -1812,21 +1819,22 @@ buildvariants: tasks: *ubuntu1404_x86_64_enterprise_tasks - name: ubuntu1604 - display_name: Ubuntu 16.04 (Go 1.8) + display_name: Ubuntu 16.04 (Go 1.10) run_on: - ubuntu1604-test expansions: - gorootvars: 'PATH="/opt/go1.8/go/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/go1.8/go' + gorootvars: 'PATH="/opt/golang/go1.10/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/golang/go1.10' build_tags: "sasl ssl" tasks: - name: dist + - name: replay-dist ####################################### # Windows Buildvariants # ####################################### - name: windows-64 - display_name: Windows 64-bit (Go 1.8) + display_name: Windows 64-bit (Go 1.10) run_on: - windows-64-vs2013-test expansions: @@ -1840,11 +1848,11 @@ buildvariants: arch: "win32/x86_64" preproc_gpm: "perl -pi -e 's/\\r\\n/\\n/g' " integration_test_args: "integration" - gorootvars: 'PATH="/cygdrive/c/go1.8/go/bin:/cygdrive/c/mingw-w64/x86_64-4.9.1-posix-seh-rt_v3-rev1/mingw64/bin:$PATH" GOROOT="c:/go1.8/go"' + gorootvars: 'PATH="/cygdrive/c/golang/go1.10/bin:/cygdrive/c/mingw-w64/x86_64-4.9.1-posix-seh-rt_v3-rev1/mingw64/bin:$PATH" GOROOT="c:/golang/go1.10"' tasks: *windows_64_tasks - name: windows-64-ssl - display_name: Windows 64-bit SSL (Go 1.8) + display_name: Windows 64-bit SSL (Go 1.10) run_on: - windows-64-vs2013-compile expansions: @@ -1861,13 +1869,13 @@ buildvariants: multiversion_override: "2.6" extension: .exe arch: "win32/x86_64" - gorootvars: 'PATH="/cygdrive/c/go1.8/go/bin:/cygdrive/c/mingw-w64/x86_64-4.9.1-posix-seh-rt_v3-rev1/mingw64/bin:$PATH" GOROOT="c:/go1.8/go"' + gorootvars: 'PATH="/cygdrive/c/golang/go1.10/bin:/cygdrive/c/mingw-w64/x86_64-4.9.1-posix-seh-rt_v3-rev1/mingw64/bin:$PATH" GOROOT="c:/golang/go1.10"' preproc_gpm: "perl -pi -e 's/\\r\\n/\\n/g' " integration_test_args: "integration,ssl" tasks: *windows_64_ssl_tasks - name: windows-64-enterprise - display_name: Windows 64-bit Enterprise (Go 1.8) + display_name: Windows 64-bit Enterprise (Go 1.10) run_on: - windows-64-vs2013-compile expansions: @@ -1885,7 +1893,7 @@ buildvariants: edition: enterprise extension: .exe arch: "win32/x86_64" - gorootvars: 'PATH="/cygdrive/c/go1.8/go/bin:/cygdrive/c/mingw-w64/x86_64-4.9.1-posix-seh-rt_v3-rev1/mingw64/bin:$PATH" GOROOT="c:/go1.8/go"' + gorootvars: 'PATH="/cygdrive/c/golang/go1.10/bin:/cygdrive/c/mingw-w64/x86_64-4.9.1-posix-seh-rt_v3-rev1/mingw64/bin:$PATH" GOROOT="c:/golang/go1.10"' preproc_gpm: "perl -pi -e 's/\\r\\n/\\n/g' " integration_test_args: "integration" tasks: *windows_64_enterprise_tasks @@ -1895,7 +1903,7 @@ buildvariants: ####################################### - name: ubuntu1604-arm64 - display_name: ZAP ARM64 Ubuntu 16.04 SSL (gccgo 1.4) + display_name: ZAP ARM64 Ubuntu 16.04 SSL (Go 1.10) run_on: - ubuntu1604-arm64-small stepback: false @@ -1906,10 +1914,9 @@ buildvariants: mongo_os: "ubuntu1604" mongo_edition: "targeted" mongo_arch: "arm64" - args: -gccgoflags "$(pkg-config --libs --cflags libcrypto libssl)" build_tags: "ssl" resmoke_use_ssl: _ssl - gorootvars: PATH="/opt/mongodbtoolchain/v2/bin/:$PATH" + gorootvars: 'PATH="/opt/golang/go1.10/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/golang/go1.10 CC=/opt/mongodbtoolchain/v2/bin/aarch64-mongodb-linux-gcc' excludes: requires_mmap_available,requires_large_ram,requires_mongo_24,requires_mongo_26,requires_mongo_30 resmoke_args: -j 2 multiversion_override: "skip" @@ -1923,7 +1930,7 @@ buildvariants: ####################################### - name: rhel71-ppc64le-enterprise - display_name: ZAP PPC64LE RHEL 7.1 Enterprise (Go 1.8) + display_name: ZAP PPC64LE RHEL 7.1 Enterprise (Go 1.10) run_on: - rhel71-power8-test stepback: false @@ -1938,7 +1945,7 @@ buildvariants: #args: ... libsasl2; build_tags "sasl ssl" build_tags: 'ssl' resmoke_use_ssl: _ssl - gorootvars: 'PATH="/opt/go1.8/go/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/go1.8/go CC=/opt/mongodbtoolchain/v2/bin/ppc64le-mongodb-linux-gcc' + gorootvars: 'PATH="/opt/golang/go1.10/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/golang/go1.10 CC=/opt/mongodbtoolchain/v2/bin/ppc64le-mongodb-linux-gcc' resmoke_args: -j 4 excludes: requires_mmap_available,requires_large_ram,requires_mongo_24,requires_mongo_26,requires_mongo_30 multiversion_override: "skip" @@ -1949,23 +1956,24 @@ buildvariants: tasks: *rhel71_ppc64le_enterprise_tasks - name: ubuntu1604-ppc64le-enterprise - display_name: ZAP PPC64LE Ubuntu 16.04 Enterprise (Go 1.8) + display_name: ZAP PPC64LE Ubuntu 16.04 Enterprise (Go 1.10) run_on: - ubuntu1604-power8-test stepback: false batchtime: 10080 # weekly expansions: - gorootvars: 'PATH="/opt/go1.8/go/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/go1.8/go CC=/opt/mongodbtoolchain/v2/bin/ppc64le-mongodb-linux-gcc' + gorootvars: 'PATH="/opt/golang/go1.10/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/golang/go1.10 CC=/opt/mongodbtoolchain/v2/bin/ppc64le-mongodb-linux-gcc' build_tags: 'ssl sasl' tasks: - name: dist + - name: replay-dist ####################################### # Z (s390x) Buildvariants # ####################################### - name: rhel67-s390x-enterprise - display_name: ZAP s390x RHEL 6.7 Enterprise (Go 1.8) + display_name: ZAP s390x RHEL 6.7 Enterprise (Go 1.10) run_on: - rhel67-zseries-test stepback: false @@ -1978,7 +1986,7 @@ buildvariants: mongo_arch: "s390x" build_tags: "sasl ssl" resmoke_use_ssl: _ssl - gorootvars: 'PATH="/opt/go1.8/go/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/go1.8/go CC=/opt/mongodbtoolchain/v2/bin/s390x-mongodb-linux-gcc' + gorootvars: 'PATH="/opt/golang/go1.10/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/golang/go1.10 CC=/opt/mongodbtoolchain/v2/bin/s390x-mongodb-linux-gcc' excludes: requires_mmap_available,requires_mongo_24,requires_mongo_26,requires_mongo_30 resmoke_args: -j 2 multiversion_override: "skip" @@ -1989,16 +1997,17 @@ buildvariants: tasks: *rhel67_s390x_enterprise_tasks - name: ubuntu1604-s390x-enterprise - display_name: ZAP s390x Ubuntu 16.04 Enterprise (Go 1.8) + display_name: ZAP s390x Ubuntu 16.04 Enterprise (Go 1.10) run_on: - ubuntu1604-zseries-small stepback: false batchtime: 10080 # weekly expansions: - gorootvars: 'PATH="/opt/go1.8/go/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/go1.8/go CC=/opt/mongodbtoolchain/v2/bin/s390x-mongodb-linux-gcc' + gorootvars: 'PATH="/opt/golang/go1.10/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/golang/go1.10 CC=/opt/mongodbtoolchain/v2/bin/s390x-mongodb-linux-gcc' build_tags: "sasl ssl" tasks: - name: dist + - name: replay-dist ####################################### # Experimental Buildvariants # @@ -2007,7 +2016,7 @@ buildvariants: - name: ubuntu-race stepback: false batchtime: 1440 # daily - display_name: z Race Detector Ubuntu 14.04 (Go 1.8) + display_name: z Race Detector Ubuntu 14.04 (Go 1.10) run_on: - ubuntu1404-test expansions: @@ -2015,7 +2024,7 @@ buildvariants: <<: *mongo_default_startup_args mongo_os: "ubuntu1404" mongo_edition: "enterprise" - gorootvars: 'PATH="/opt/go1.8/go/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/go1.8/go' + gorootvars: 'PATH="/opt/golang/go1.10/bin:/opt/mongodbtoolchain/v2/bin/:$PATH" GOROOT=/opt/golang/go1.10' build_tags: "sasl ssl" arch: "linux/x86_64" args: "-race" diff --git a/src/mongo/gotools/common/db/openssl/openssl.go b/src/mongo/gotools/common/db/openssl/openssl.go index fc39c187f54..cb744ad5dd0 100644 --- a/src/mongo/gotools/common/db/openssl/openssl.go +++ b/src/mongo/gotools/common/db/openssl/openssl.go @@ -107,7 +107,10 @@ func setupCtx(opts options.ToolOptions) (*openssl.Ctx, error) { var err error for _, sslInitFunc := range sslInitializationFunctions { - sslInitFunc(opts) + err = sslInitFunc(opts) + if err != nil { + return nil, err + } } if ctx, err = openssl.NewCtxWithVersion(openssl.AnyVersion); err != nil { diff --git a/src/mongo/gotools/common/db/openssl/openssl_fips.go b/src/mongo/gotools/common/db/openssl/openssl_fips.go index 08a0f644cb8..68bf0a92d3d 100644 --- a/src/mongo/gotools/common/db/openssl/openssl_fips.go +++ b/src/mongo/gotools/common/db/openssl/openssl_fips.go @@ -18,6 +18,8 @@ import ( func init() { if openssl.FIPSModeDefined() { sslInitializationFunctions = append(sslInitializationFunctions, SetUpFIPSMode) + } else { + sslInitializationFunctions = append(sslInitializationFunctions, NoFIPSModeAvailable) } } @@ -27,3 +29,10 @@ func SetUpFIPSMode(opts options.ToolOptions) error { } return nil } + +func NoFIPSModeAvailable(opts options.ToolOptions) error { + if opts.SSLFipsMode { + return fmt.Errorf("FIPS mode not supported") + } + return nil +} diff --git a/src/mongo/gotools/common/lldb/connector.go b/src/mongo/gotools/common/lldb/connector.go new file mode 100644 index 00000000000..b1623243528 --- /dev/null +++ b/src/mongo/gotools/common/lldb/connector.go @@ -0,0 +1,81 @@ +// Copyright (C) MongoDB, Inc. 2014-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package lldb + +import ( + "net" + "time" + + mgo "github.com/10gen/llmgo" + "github.com/mongodb/mongo-tools/common/lldb/kerberos" + "github.com/mongodb/mongo-tools/common/options" + "github.com/mongodb/mongo-tools/common/util" +) + +// Interface type for connecting to the database. +type DBConnector interface { + // configure, based on the options passed in + Configure(options.ToolOptions) error + + // dial the database and get a fresh new session + GetNewSession() (*mgo.Session, error) +} + +// Basic connector for dialing the database, with no authentication. +type VanillaDBConnector struct { + dialInfo *mgo.DialInfo +} + +// Configure sets up the db connector using the options in opts. It parses the +// connection string and then sets up the dial information using the default +// dial timeout. +func (self *VanillaDBConnector) Configure(opts options.ToolOptions) error { + timeout := time.Duration(opts.Timeout) * time.Second + + // create the dialer func that will be used to connect + dialer := func(addr *mgo.ServerAddr) (net.Conn, error) { + conn, err := net.DialTimeout("tcp", addr.String(), timeout) + if err != nil { + return nil, err + } + // enable TCP keepalive + err = util.EnableTCPKeepAlive(conn, time.Duration(opts.TCPKeepAliveSeconds)*time.Second) + if err != nil { + return nil, err + } + return conn, nil + } + + // set up the dial info + self.dialInfo = &mgo.DialInfo{ + Direct: opts.Direct, + ReplicaSetName: opts.ReplicaSetName, + Username: opts.Auth.Username, + Password: opts.Auth.Password, + Source: opts.GetAuthenticationDatabase(), + Mechanism: opts.Auth.Mechanism, + DialServer: dialer, + Timeout: timeout, + } + + // create or fetch the addresses to be used to connect + if opts.URI != nil && opts.URI.ConnectionString != "" { + self.dialInfo.Addrs = opts.URI.GetConnectionAddrs() + } else { + self.dialInfo.Addrs = util.CreateConnectionAddrs(opts.Host, opts.Port) + } + + kerberos.AddKerberosOpts(opts, self.dialInfo) + + return nil +} + +// GetNewSession connects to the server and returns the established session and any +// error encountered. +func (self *VanillaDBConnector) GetNewSession() (*mgo.Session, error) { + return mgo.DialWithInfo(self.dialInfo) +} diff --git a/src/mongo/gotools/common/lldb/db.go b/src/mongo/gotools/common/lldb/db.go new file mode 100644 index 00000000000..a3397baff56 --- /dev/null +++ b/src/mongo/gotools/common/lldb/db.go @@ -0,0 +1,262 @@ +// Copyright (C) MongoDB, Inc. 2014-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +// Package db implements generic connection to MongoDB, and contains +// subpackages for specific methods of connection. +package lldb + +import ( + "github.com/mongodb/mongo-tools/common/options" + "github.com/mongodb/mongo-tools/common/password" + mgo "github.com/10gen/llmgo" + "github.com/10gen/llmgo/bson" + + "fmt" + "io" + "strings" + "sync" +) + +type ( + sessionFlag uint32 + // Used to get appropriate the DBConnector(s) based on opts + GetConnectorFunc func(opts options.ToolOptions) DBConnector +) + +// Session flags. +const ( + None sessionFlag = 0 + Monotonic sessionFlag = 1 << iota + DisableSocketTimeout +) + +// MongoDB enforced limits. +const ( + MaxBSONSize = 16 * 1024 * 1024 // 16MB - maximum BSON document size +) + +// Default port for integration tests +const ( + DefaultTestPort = "33333" +) + +const ( + ErrLostConnection = "lost connection to server" + ErrNoReachableServers = "no reachable servers" + ErrNsNotFound = "ns not found" + // replication errors list the replset name if we are talking to a mongos, + // so we can only check for this universal prefix + ErrReplTimeoutPrefix = "waiting for replication timed out" + ErrCouldNotContactPrimaryPrefix = "could not contact primary for replica set" + ErrWriteResultsUnavailable = "write results unavailable from" + ErrCouldNotFindPrimaryPrefix = `could not find host matching read preference { mode: "primary"` + ErrUnableToTargetPrefix = "unable to target" + ErrNotMaster = "not master" + ErrConnectionRefusedSuffix = "Connection refused" +) + +var ( + GetConnectorFuncs = []GetConnectorFunc{} +) + +// Used to manage database sessions +type SessionProvider struct { + + // For connecting to the database + connector DBConnector + + // used to avoid a race condition around creating the master session + masterSessionLock sync.Mutex + + // the master session to use for connection pooling + masterSession *mgo.Session + + // flags for generating the master session + bypassDocumentValidation bool + flags sessionFlag + readPreference mgo.Mode + tags bson.D +} + +// ApplyOpsResponse represents the response from an 'applyOps' command. +type ApplyOpsResponse struct { + Ok bool `bson:"ok"` + ErrMsg string `bson:"errmsg"` +} + +// Oplog represents a MongoDB oplog document. +type Oplog struct { + Timestamp bson.MongoTimestamp `bson:"ts"` + HistoryID int64 `bson:"h"` + Version int `bson:"v"` + Operation string `bson:"op"` + Namespace string `bson:"ns"` + Object bson.D `bson:"o"` + Query bson.D `bson:"o2"` + UI *bson.Binary `bson:"ui,omitempty"` +} + +// Returns a session connected to the database server for which the +// session provider is configured. +func (self *SessionProvider) GetSession() (*mgo.Session, error) { + self.masterSessionLock.Lock() + defer self.masterSessionLock.Unlock() + + // The master session is initialized + if self.masterSession != nil { + return self.masterSession.Copy(), nil + } + + // initialize the provider's master session + var err error + self.masterSession, err = self.connector.GetNewSession() + if err != nil { + return nil, fmt.Errorf("error connecting to db server: %v", err) + } + + // update masterSession based on flags + self.refresh() + + // copy the provider's master session, for connection pooling + return self.masterSession.Copy(), nil +} + +// Close closes the master session in the connection pool +func (self *SessionProvider) Close() { + self.masterSessionLock.Lock() + defer self.masterSessionLock.Unlock() + if self.masterSession != nil { + self.masterSession.Close() + } +} + +// refresh is a helper for modifying the session based on the +// session provider flags passed in with SetFlags. +// This helper assumes a lock is already taken. +func (self *SessionProvider) refresh() { + // handle bypassDocumentValidation + self.masterSession.SetBypassValidation(self.bypassDocumentValidation) + + // handle readPreference + self.masterSession.SetMode(self.readPreference, true) + + // disable timeouts + if (self.flags & DisableSocketTimeout) > 0 { + self.masterSession.SetSocketTimeout(0) + } + if self.tags != nil { + self.masterSession.SelectServers(self.tags) + } +} + +// SetFlags allows certain modifications to the masterSession after initial creation. +func (self *SessionProvider) SetFlags(flagBits sessionFlag) { + self.masterSessionLock.Lock() + defer self.masterSessionLock.Unlock() + + self.flags = flagBits + + // make sure we update the master session if one already exists + if self.masterSession != nil { + self.refresh() + } +} + +// SetReadPreference sets the read preference mode in the SessionProvider +// and eventually in the masterSession +func (self *SessionProvider) SetReadPreference(pref mgo.Mode) { + self.masterSessionLock.Lock() + defer self.masterSessionLock.Unlock() + + self.readPreference = pref + + if self.masterSession != nil { + self.refresh() + } +} + +// SetBypassDocumentValidation sets whether to bypass document validation in the SessionProvider +// and eventually in the masterSession +func (self *SessionProvider) SetBypassDocumentValidation(bypassDocumentValidation bool) { + self.masterSessionLock.Lock() + defer self.masterSessionLock.Unlock() + + self.bypassDocumentValidation = bypassDocumentValidation + + if self.masterSession != nil { + self.refresh() + } +} + +// SetTags sets the server selection tags in the SessionProvider +// and eventually in the masterSession +func (self *SessionProvider) SetTags(tags bson.D) { + self.masterSessionLock.Lock() + defer self.masterSessionLock.Unlock() + + self.tags = tags + + if self.masterSession != nil { + self.refresh() + } +} + +// NewSessionProvider constructs a session provider but does not attempt to +// create the initial session. +func NewSessionProvider(opts options.ToolOptions) (*SessionProvider, error) { + // create the provider + provider := &SessionProvider{ + readPreference: mgo.Primary, + bypassDocumentValidation: false, + } + + // finalize auth options, filling in missing passwords + if opts.Auth.ShouldAskForPassword() { + opts.Auth.Password = password.Prompt() + } + + // create the connector for dialing the database + provider.connector = getConnector(opts) + + // configure the connector + err := provider.connector.Configure(opts) + if err != nil { + return nil, fmt.Errorf("error configuring the connector: %v", err) + } + return provider, nil +} + +// IsConnectionError returns a boolean indicating if a given error is due to +// an error in an underlying DB connection (as opposed to some other write +// failure such as a duplicate key error) +func IsConnectionError(err error) bool { + if err == nil { + return false + } + lowerCaseError := strings.ToLower(err.Error()) + if lowerCaseError == ErrNoReachableServers || + err == io.EOF || + strings.Contains(lowerCaseError, ErrReplTimeoutPrefix) || + strings.Contains(lowerCaseError, ErrCouldNotContactPrimaryPrefix) || + strings.Contains(lowerCaseError, ErrWriteResultsUnavailable) || + strings.Contains(lowerCaseError, ErrCouldNotFindPrimaryPrefix) || + strings.Contains(lowerCaseError, ErrUnableToTargetPrefix) || + lowerCaseError == ErrNotMaster || + strings.HasSuffix(lowerCaseError, ErrConnectionRefusedSuffix) { + return true + } + return false +} + +// Get the right type of connector, based on the options +func getConnector(opts options.ToolOptions) DBConnector { + for _, getConnectorFunc := range GetConnectorFuncs { + if connector := getConnectorFunc(opts); connector != nil { + return connector + } + } + return &VanillaDBConnector{} +} diff --git a/src/mongo/gotools/common/lldb/db_openssl.go b/src/mongo/gotools/common/lldb/db_openssl.go new file mode 100644 index 00000000000..4a313972060 --- /dev/null +++ b/src/mongo/gotools/common/lldb/db_openssl.go @@ -0,0 +1,26 @@ +// Copyright (C) MongoDB, Inc. 2014-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +// +build ssl,!openssl_pre_1.0 + +package lldb + +import ( + "github.com/mongodb/mongo-tools/common/lldb/openssl" + "github.com/mongodb/mongo-tools/common/options" +) + +func init() { + GetConnectorFuncs = append(GetConnectorFuncs, getSSLConnector) +} + +// return the SSL DB connector if using SSL, otherwise, return nil. +func getSSLConnector(opts options.ToolOptions) DBConnector { + if opts.SSL.UseSSL { + return &openssl.SSLDBConnector{} + } + return nil +} diff --git a/src/mongo/gotools/common/lldb/db_tlsgo.go b/src/mongo/gotools/common/lldb/db_tlsgo.go new file mode 100644 index 00000000000..e1cfcf18e17 --- /dev/null +++ b/src/mongo/gotools/common/lldb/db_tlsgo.go @@ -0,0 +1,26 @@ +// Copyright (C) MongoDB, Inc. 2014-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +// +build ssl,openssl_pre_1.0 + +package lldb + +import ( + "github.com/mongodb/mongo-tools/common/lldb/tlsgo" + "github.com/mongodb/mongo-tools/common/options" +) + +func init() { + GetConnectorFuncs = append(GetConnectorFuncs, getSSLConnector) +} + +// return the SSL DB connector if using SSL, otherwise, return nil. +func getSSLConnector(opts options.ToolOptions) DBConnector { + if opts.SSL.UseSSL { + return &tlsgo.TLSDBConnector{} + } + return nil +} diff --git a/src/mongo/gotools/common/lldb/kerberos/gssapi.go b/src/mongo/gotools/common/lldb/kerberos/gssapi.go new file mode 100644 index 00000000000..168e63636c7 --- /dev/null +++ b/src/mongo/gotools/common/lldb/kerberos/gssapi.go @@ -0,0 +1,34 @@ +// Copyright (C) MongoDB, Inc. 2014-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +// Package kerberos implements authentication to MongoDB using kerberos +package kerberos + +// #cgo windows CFLAGS: -Ic:/sasl/include +// #cgo windows LDFLAGS: -Lc:/sasl/lib + +import ( + "github.com/mongodb/mongo-tools/common/options" + mgo "github.com/10gen/llmgo" +) + +const authMechanism = "GSSAPI" + +func AddKerberosOpts(opts options.ToolOptions, dialInfo *mgo.DialInfo) { + if dialInfo == nil { + return + } + if opts.Kerberos == nil { + return + } + if opts.Auth == nil || (opts.Auth.Mechanism != authMechanism && + dialInfo.Mechanism != authMechanism) { + return + } + dialInfo.Service = opts.Kerberos.Service + dialInfo.ServiceHost = opts.Kerberos.ServiceHost + dialInfo.Mechanism = authMechanism +} diff --git a/src/mongo/gotools/common/lldb/openssl/openssl.go b/src/mongo/gotools/common/lldb/openssl/openssl.go new file mode 100644 index 00000000000..b07019a7956 --- /dev/null +++ b/src/mongo/gotools/common/lldb/openssl/openssl.go @@ -0,0 +1,194 @@ +// Copyright (C) MongoDB, Inc. 2014-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +// +build ssl,!openssl_pre_1.0 + +// Package openssl implements connection to MongoDB over ssl. +package openssl + +import ( + "fmt" + "net" + "time" + + mgo "github.com/10gen/llmgo" + "github.com/10gen/openssl" + "github.com/mongodb/mongo-tools/common/lldb/kerberos" + "github.com/mongodb/mongo-tools/common/log" + "github.com/mongodb/mongo-tools/common/options" + "github.com/mongodb/mongo-tools/common/util" +) + +// For connecting to the database over ssl +type SSLDBConnector struct { + dialInfo *mgo.DialInfo + ctx *openssl.Ctx +} + +// Configure the connector to connect to the server over ssl. Parses the +// connection string, and sets up the correct function to dial the server +// based on the ssl options passed in. +func (self *SSLDBConnector) Configure(opts options.ToolOptions) error { + + var err error + self.ctx, err = setupCtx(opts) + if err != nil { + return fmt.Errorf("openssl configuration: %v", err) + } + + var flags openssl.DialFlags + flags = 0 + if opts.SSLAllowInvalidCert || opts.SSLAllowInvalidHost { + flags = openssl.InsecureSkipHostVerification + } + // create the dialer func that will be used to connect + dialer := func(addr *mgo.ServerAddr) (net.Conn, error) { + conn, err := openssl.Dial("tcp", addr.String(), self.ctx, flags) + if err != nil { + // mgo discards dialer errors so log it now + log.Logvf(log.Always, "error dialing %v: %v", addr.String(), err) + return nil, err + } + // enable TCP keepalive + err = util.EnableTCPKeepAlive(conn.UnderlyingConn(), time.Duration(opts.TCPKeepAliveSeconds)*time.Second) + if err != nil { + // mgo discards dialer errors so log it now + log.Logvf(log.Always, "error enabling TCP keepalive on connection to %v: %v", addr.String(), err) + conn.Close() + return nil, err + } + return conn, nil + } + + timeout := time.Duration(opts.Timeout) * time.Second + + // set up the dial info + self.dialInfo = &mgo.DialInfo{ + Timeout: timeout, + Direct: opts.Direct, + ReplicaSetName: opts.ReplicaSetName, + DialServer: dialer, + Username: opts.Auth.Username, + Password: opts.Auth.Password, + Source: opts.GetAuthenticationDatabase(), + Mechanism: opts.Auth.Mechanism, + } + + // create or fetch the addresses to be used to connect + if opts.URI != nil && opts.URI.ConnectionString != "" { + self.dialInfo.Addrs = opts.URI.GetConnectionAddrs() + } else { + self.dialInfo.Addrs = util.CreateConnectionAddrs(opts.Host, opts.Port) + } + kerberos.AddKerberosOpts(opts, self.dialInfo) + return nil + +} + +// Dial the server. +func (self *SSLDBConnector) GetNewSession() (*mgo.Session, error) { + return mgo.DialWithInfo(self.dialInfo) +} + +// To be handed to mgo.DialInfo for connecting to the server. +type dialerFunc func(addr *mgo.ServerAddr) (net.Conn, error) + +// Handle optionally compiled SSL initialization functions (fips mode set) +type sslInitializationFunction func(options.ToolOptions) error + +var sslInitializationFunctions []sslInitializationFunction + +// Creates and configures an openssl.Ctx +func setupCtx(opts options.ToolOptions) (*openssl.Ctx, error) { + var ctx *openssl.Ctx + var err error + + for _, sslInitFunc := range sslInitializationFunctions { + err = sslInitFunc(opts) + if err != nil { + return nil, err + } + } + + if ctx, err = openssl.NewCtxWithVersion(openssl.AnyVersion); err != nil { + return nil, fmt.Errorf("failure creating new openssl context with "+ + "NewCtxWithVersion(AnyVersion): %v", err) + } + + // OpAll - Activate all bug workaround options, to support buggy client SSL's. + // NoSSLv2 - Disable SSL v2 support + ctx.SetOptions(openssl.OpAll | openssl.NoSSLv2) + + // HIGH - Enable strong ciphers + // !EXPORT - Disable export ciphers (40/56 bit) + // !aNULL - Disable anonymous auth ciphers + // @STRENGTH - Sort ciphers based on strength + ctx.SetCipherList("HIGH:!EXPORT:!aNULL@STRENGTH") + + // add the PEM key file with the cert and private key, if specified + if opts.SSLPEMKeyFile != "" { + if err = ctx.UseCertificateChainFile(opts.SSLPEMKeyFile); err != nil { + return nil, fmt.Errorf("UseCertificateChainFile: %v", err) + } + if opts.SSLPEMKeyPassword != "" { + if err = ctx.UsePrivateKeyFileWithPassword( + opts.SSLPEMKeyFile, openssl.FiletypePEM, opts.SSLPEMKeyPassword); err != nil { + return nil, fmt.Errorf("UsePrivateKeyFile: %v", err) + } + } else { + if err = ctx.UsePrivateKeyFile(opts.SSLPEMKeyFile, openssl.FiletypePEM); err != nil { + return nil, fmt.Errorf("UsePrivateKeyFile: %v", err) + } + } + // Verify that the certificate and the key go together. + if err = ctx.CheckPrivateKey(); err != nil { + return nil, fmt.Errorf("CheckPrivateKey: %v", err) + } + } + + // If renegotiation is needed, don't return from recv() or send() until it's successful. + // Note: this is for blocking sockets only. + ctx.SetMode(openssl.AutoRetry) + + // Disable session caching (see SERVER-10261) + ctx.SetSessionCacheMode(openssl.SessionCacheOff) + + if opts.SSLCAFile != "" { + calist, err := openssl.LoadClientCAFile(opts.SSLCAFile) + if err != nil { + return nil, fmt.Errorf("LoadClientCAFile: %v", err) + } + ctx.SetClientCAList(calist) + if err = ctx.LoadVerifyLocations(opts.SSLCAFile, ""); err != nil { + return nil, fmt.Errorf("LoadVerifyLocations: %v", err) + } + } else { + err = ctx.SetupSystemCA() + if err != nil { + return nil, fmt.Errorf("Error setting up system certificate authority: %v", err) + } + } + + var verifyOption openssl.VerifyOptions + if opts.SSLAllowInvalidCert { + verifyOption = openssl.VerifyNone + } else { + verifyOption = openssl.VerifyPeer + } + ctx.SetVerify(verifyOption, nil) + + if opts.SSLCRLFile != "" { + store := ctx.GetCertificateStore() + store.SetFlags(openssl.CRLCheck) + lookup, err := store.AddLookup(openssl.X509LookupFile()) + if err != nil { + return nil, fmt.Errorf("AddLookup(X509LookupFile()): %v", err) + } + lookup.LoadCRLFile(opts.SSLCRLFile) + } + + return ctx, nil +} diff --git a/src/mongo/gotools/common/lldb/openssl/openssl_fips.go b/src/mongo/gotools/common/lldb/openssl/openssl_fips.go new file mode 100644 index 00000000000..68bf0a92d3d --- /dev/null +++ b/src/mongo/gotools/common/lldb/openssl/openssl_fips.go @@ -0,0 +1,38 @@ +// Copyright (C) MongoDB, Inc. 2014-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +// +build ssl,!openssl_pre_1.0 + +package openssl + +import ( + "fmt" + + "github.com/10gen/openssl" + "github.com/mongodb/mongo-tools/common/options" +) + +func init() { + if openssl.FIPSModeDefined() { + sslInitializationFunctions = append(sslInitializationFunctions, SetUpFIPSMode) + } else { + sslInitializationFunctions = append(sslInitializationFunctions, NoFIPSModeAvailable) + } +} + +func SetUpFIPSMode(opts options.ToolOptions) error { + if err := openssl.FIPSModeSet(opts.SSLFipsMode); err != nil { + return fmt.Errorf("couldn't set FIPS mode to %v: %v", opts.SSLFipsMode, err) + } + return nil +} + +func NoFIPSModeAvailable(opts options.ToolOptions) error { + if opts.SSLFipsMode { + return fmt.Errorf("FIPS mode not supported") + } + return nil +} diff --git a/src/mongo/gotools/common/lldb/tlsgo/config.go b/src/mongo/gotools/common/lldb/tlsgo/config.go new file mode 100644 index 00000000000..8d3971b537b --- /dev/null +++ b/src/mongo/gotools/common/lldb/tlsgo/config.go @@ -0,0 +1,246 @@ +// Copyright (C) MongoDB, Inc. 2018-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +// This file contains code adapted from the MongoDB Go Driver. + +// Package tlsgo provides a mgo connection using Go's native TLS library. +package tlsgo + +import ( + "crypto/tls" + "crypto/x509" + "encoding/asn1" + "encoding/hex" + "encoding/pem" + "fmt" + "io/ioutil" + "strings" +) + +// TLSConfig contains options for configuring an SSL connection to the server. +type TLSConfig struct { + caCert *x509.Certificate + clientCert *tls.Certificate + insecure bool +} + +// NewTLSConfig creates a new TLSConfig. +func NewTLSConfig() *TLSConfig { + cfg := &TLSConfig{} + + return cfg +} + +// SetInsecure sets whether the client should verify the server's certificate chain and hostnames. +func (c *TLSConfig) SetInsecure(allow bool) { + c.insecure = allow +} + +// AddClientCertFromFile adds a client certificate to the configuration given a path to the +// containing file and returns the certificate's subject name. +func (c *TLSConfig) AddClientCertFromFile(clientFile, password string) (string, error) { + data, err := ioutil.ReadFile(clientFile) + if err != nil { + return "", err + } + + certPEM, err := loadPEMBlock(data, "CERTIFICATE") + if err != nil { + return "", err + } + + keyPEM, err := loadPEMBlock(data, "PRIVATE KEY") + if err != nil { + return "", err + } + // This check only covers encrypted PEM data with a DEK-Info header. It + // does not detect unencrypted PEM containing PKCS#8 format data with an + // encrypted private key. + if x509.IsEncryptedPEMBlock(keyPEM) { + if password == "" { + return "", fmt.Errorf("No password provided to decrypt private key") + } + decrypted, err := x509.DecryptPEMBlock(keyPEM, []byte(password)) + if err != nil { + return "", err + } + keyPEM = &pem.Block{Bytes: decrypted, Type: keyPEM.Type} + } + + if strings.Contains(keyPEM.Type, "ENCRYPTED") { + return "", fmt.Errorf("PKCS#8 encrypted private keys are not supported") + } + + cert, err := tls.X509KeyPair(pem.EncodeToMemory(certPEM), pem.EncodeToMemory(keyPEM)) + if err != nil { + return "", err + } + + c.clientCert = &cert + + // The documentation for the tls.X509KeyPair indicates that the Leaf + // certificate is not retained. Because there isn't any way of creating a + // tls.Certificate from an x509.Certificate short of calling X509KeyPair + // on the raw bytes, we're forced to parse the certificate over again to + // get the subject name. + crt, err := x509.ParseCertificate(certPEM.Bytes) + if err != nil { + return "", err + } + + return x509CertSubject(crt), nil +} + +// AddCaCertFromFile adds a root CA certificate to the configuration given a path to the containing file. +func (c *TLSConfig) AddCaCertFromFile(caFile string) error { + data, err := ioutil.ReadFile(caFile) + if err != nil { + return err + } + + certBytes, err := loadCertBytes(data) + if err != nil { + return err + } + + cert, err := x509.ParseCertificate(certBytes) + if err != nil { + return err + } + + c.caCert = cert + + return nil +} + +// MakeConfig constructs a new tls.Config from the configuration specified. +func (c *TLSConfig) MakeConfig() (*tls.Config, error) { + cfg := &tls.Config{} + + if c.clientCert != nil { + cfg.Certificates = []tls.Certificate{*c.clientCert} + } + + if c.caCert == nil { + roots, err := loadSystemCAs() + if err != nil { + return nil, err + } + cfg.RootCAs = roots + } else { + cfg.RootCAs = x509.NewCertPool() + cfg.RootCAs.AddCert(c.caCert) + } + + cfg.InsecureSkipVerify = c.insecure + + return cfg, nil +} + +func loadCertBytes(data []byte) ([]byte, error) { + b, err := loadPEMBlock(data, "CERTIFICATE") + if err != nil { + return nil, err + } + return b.Bytes, nil +} + +func loadPEMBlock(data []byte, blocktype string) (*pem.Block, error) { + var b *pem.Block + + for b == nil { + if data == nil || len(data) == 0 { + return nil, fmt.Errorf("no block of type %s found in .pem file", blocktype) + } + + block, rest := pem.Decode(data) + if block == nil { + return nil, fmt.Errorf("invalid .pem file") + } + + if strings.Contains(block.Type, blocktype) { + if b != nil { + return nil, fmt.Errorf("multiple %s sections in .pem file", blocktype) + } + b = block + } + + data = rest + } + + return b, nil +} + +// Because the functionality to convert a pkix.Name to a string wasn't added until Go 1.10, we +// need to copy the implementation (along with the attributeTypeNames map below). +func x509CertSubject(cert *x509.Certificate) string { + r := cert.Subject.ToRDNSequence() + + s := "" + for i := 0; i < len(r); i++ { + rdn := r[len(r)-1-i] + if i > 0 { + s += "," + } + for j, tv := range rdn { + if j > 0 { + s += "+" + } + + oidString := tv.Type.String() + typeName, ok := attributeTypeNames[oidString] + if !ok { + derBytes, err := asn1.Marshal(tv.Value) + if err == nil { + s += oidString + "=#" + hex.EncodeToString(derBytes) + continue // No value escaping necessary. + } + + typeName = oidString + } + + valueString := fmt.Sprint(tv.Value) + escaped := make([]rune, 0, len(valueString)) + + for k, c := range valueString { + escape := false + + switch c { + case ',', '+', '"', '\\', '<', '>', ';': + escape = true + + case ' ': + escape = k == 0 || k == len(valueString)-1 + + case '#': + escape = k == 0 + } + + if escape { + escaped = append(escaped, '\\', c) + } else { + escaped = append(escaped, c) + } + } + + s += typeName + "=" + string(escaped) + } + } + + return s +} + +var attributeTypeNames = map[string]string{ + "2.5.4.6": "C", + "2.5.4.10": "O", + "2.5.4.11": "OU", + "2.5.4.3": "CN", + "2.5.4.5": "SERIALNUMBER", + "2.5.4.7": "L", + "2.5.4.8": "ST", + "2.5.4.9": "STREET", + "2.5.4.17": "POSTALCODE", +} diff --git a/src/mongo/gotools/common/lldb/tlsgo/rootcerts.go b/src/mongo/gotools/common/lldb/tlsgo/rootcerts.go new file mode 100644 index 00000000000..ee3ec3769f1 --- /dev/null +++ b/src/mongo/gotools/common/lldb/tlsgo/rootcerts.go @@ -0,0 +1,22 @@ +// Copyright (C) MongoDB, Inc. 2018-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Based on https://github.com/hashicorp/go-rootcerts by HashiCorp +// See THIRD-PARTY-NOTICES for original license terms. + +// +build !darwin + +package tlsgo + +import ( + "crypto/x509" +) + +// Stubbed for non-darwin systems. By returning nil, the Go library +// will use its own code for finding system certs. +func loadSystemCAs() (*x509.CertPool, error) { + return nil, nil +} diff --git a/src/mongo/gotools/common/lldb/tlsgo/rootcerts_darwin.go b/src/mongo/gotools/common/lldb/tlsgo/rootcerts_darwin.go new file mode 100644 index 00000000000..72c7a9116ad --- /dev/null +++ b/src/mongo/gotools/common/lldb/tlsgo/rootcerts_darwin.go @@ -0,0 +1,58 @@ +// Copyright (C) MongoDB, Inc. 2018-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Based on https://github.com/hashicorp/go-rootcerts by HashiCorp +// See THIRD-PARTY-NOTICES for original license terms. + +package tlsgo + +import ( + "crypto/x509" + "os/exec" + "os/user" + "path" +) + +// loadSystemCAs has special behavior on Darwin systems to work around +// bugs loading certs from keychains. See this GitHub issues query: +// https://github.com/golang/go/issues?utf8=%E2%9C%93&q=is%3Aissue+darwin+keychain +func loadSystemCAs() (*x509.CertPool, error) { + pool := x509.NewCertPool() + + for _, keychain := range certKeychains() { + err := addCertsFromKeychain(pool, keychain) + if err != nil { + return nil, err + } + } + + return pool, nil +} + +func addCertsFromKeychain(pool *x509.CertPool, keychain string) error { + cmd := exec.Command("/usr/bin/security", "find-certificate", "-a", "-p", keychain) + data, err := cmd.Output() + if err != nil { + return err + } + + pool.AppendCertsFromPEM(data) + + return nil +} + +func certKeychains() []string { + keychains := []string{ + "/System/Library/Keychains/SystemRootCertificates.keychain", + "/Library/Keychains/System.keychain", + } + user, err := user.Current() + if err == nil { + loginKeychain := path.Join(user.HomeDir, "Library", "Keychains", "login.keychain") + keychains = append(keychains, loginKeychain) + } + return keychains +} diff --git a/src/mongo/gotools/common/lldb/tlsgo/tlsgo.go b/src/mongo/gotools/common/lldb/tlsgo/tlsgo.go new file mode 100644 index 00000000000..2b11e991ca1 --- /dev/null +++ b/src/mongo/gotools/common/lldb/tlsgo/tlsgo.go @@ -0,0 +1,135 @@ +// Copyright (C) MongoDB, Inc. 2014-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +// Package tlsgo implements connection to MongoDB with Go native TLS. +package tlsgo + +import ( + "crypto/tls" + "fmt" + "net" + "strings" + "time" + + mgo "github.com/10gen/llmgo" + "github.com/mongodb/mongo-tools/common/lldb/kerberos" + "github.com/mongodb/mongo-tools/common/log" + "github.com/mongodb/mongo-tools/common/options" + "github.com/mongodb/mongo-tools/common/util" +) + +// TLSDBConnector makes a connection to the database with Go native TLS. +type TLSDBConnector struct { + dialInfo *mgo.DialInfo + config *TLSConfig +} + +// Configure the connector to connect to the server over ssl. Sets up the +// correct function to dial the server based on the ssl options passed in. +func (c *TLSDBConnector) Configure(opts options.ToolOptions) error { + if opts.SSLFipsMode { + return fmt.Errorf("FIPS mode not supported") + } + + if opts.SSLCRLFile != "" { + return fmt.Errorf("CRL files are not supported on this platform") + } + + c.config = NewTLSConfig() + + if opts.SSLAllowInvalidCert || opts.SSLAllowInvalidHost { + c.config.SetInsecure(true) + } + + if opts.SSLPEMKeyFile != "" { + subject, err := c.config.AddClientCertFromFile(opts.SSLPEMKeyFile, opts.SSLPEMKeyPassword) + if err != nil { + return err + } + if opts.Auth.Mechanism == "MONGODB-X509" && opts.Auth.Username == "" { + opts.Auth.Username = subject + } + } + + if opts.SSLCAFile != "" { + c.config.AddCaCertFromFile(opts.SSLCAFile) + } + + // set up the dial info + c.dialInfo = &mgo.DialInfo{ + Timeout: time.Duration(opts.Timeout) * time.Second, + Direct: opts.Direct, + ReplicaSetName: opts.ReplicaSetName, + DialServer: c.makeDialer(opts), + Username: opts.Auth.Username, + Password: opts.Auth.Password, + Source: opts.GetAuthenticationDatabase(), + Mechanism: opts.Auth.Mechanism, + } + + // create or fetch the addresses to be used to connect + if opts.URI != nil && opts.URI.ConnectionString != "" { + c.dialInfo.Addrs = opts.URI.GetConnectionAddrs() + } else { + c.dialInfo.Addrs = util.CreateConnectionAddrs(opts.Host, opts.Port) + } + kerberos.AddKerberosOpts(opts, c.dialInfo) + return nil +} + +// GetNewSession dials the server. +func (c *TLSDBConnector) GetNewSession() (*mgo.Session, error) { + return mgo.DialWithInfo(c.dialInfo) +} + +// To be handed to mgo.DialInfo for connecting to the server. +type dialerFunc func(addr *mgo.ServerAddr) (net.Conn, error) + +func (c *TLSDBConnector) makeDialer(opts options.ToolOptions) dialerFunc { + return func(addr *mgo.ServerAddr) (net.Conn, error) { + address := addr.String() + conn, err := net.Dial("tcp", address) + if err != nil { + // mgo discards dialer errors so log it now + log.Logvf(log.Always, "error dialing %v: %v", address, err) + return nil, err + } + // enable TCP keepalive + err = util.EnableTCPKeepAlive(conn, time.Duration(opts.TCPKeepAliveSeconds)*time.Second) + if err != nil { + // mgo discards dialer errors so log it now + log.Logvf(log.Always, "error enabling TCP keepalive on connection to %v: %v", address, err) + conn.Close() + return nil, err + } + + tlsConfig, err := c.config.MakeConfig() + if err != nil { + return nil, err + } + + if !tlsConfig.InsecureSkipVerify { + colonPos := strings.LastIndex(address, ":") + if colonPos == -1 { + colonPos = len(address) + } + + hostname := address[:colonPos] + tlsConfig.ServerName = hostname + } + + client := tls.Client(conn, tlsConfig) + err = client.Handshake() + if err != nil { + // mgo discards dialer errors so log it now + log.Logvf(log.Always, "error doing TLS handshake with %v: %v", address, err) + client.Close() + return nil, err + } + + return client, nil + } +} diff --git a/src/mongo/gotools/common/options/options_ssl.go b/src/mongo/gotools/common/options/options_ssl.go index de11cf9686a..4220c6d909e 100644 --- a/src/mongo/gotools/common/options/options_ssl.go +++ b/src/mongo/gotools/common/options/options_ssl.go @@ -10,6 +10,7 @@ package options func init() { ConnectionOptFunctions = append(ConnectionOptFunctions, registerSSLOptions) + BuiltWithSSL = true } func registerSSLOptions(self *ToolOptions) error { @@ -20,6 +21,5 @@ func registerSSLOptions(self *ToolOptions) error { if self.enabledOptions.URI { self.URI.AddKnownURIParameters(KnownURIOptionsSSL) } - BuiltWithSSL = true return nil } diff --git a/src/mongo/gotools/import.data b/src/mongo/gotools/import.data index be481764426..d59a8e57105 100644 --- a/src/mongo/gotools/import.data +++ b/src/mongo/gotools/import.data @@ -1,5 +1,5 @@ { - "commit": "37adadadd5ffbbdf5e42e6dc3cd8f5107e47ea56", + "commit": "5f036603357e3d910e4d765369261fd0b577dd59", "github": "mongodb/mongo-tools.git", "vendor": "tools", "branch": "v4.1" diff --git a/src/mongo/gotools/mongoreplay/log_wrapper.go b/src/mongo/gotools/mongoreplay/log_wrapper.go index 6c1e7cb6387..82e93071af7 100644 --- a/src/mongo/gotools/mongoreplay/log_wrapper.go +++ b/src/mongo/gotools/mongoreplay/log_wrapper.go @@ -69,3 +69,8 @@ func (lw *logWrapper) Logv(minVerb int, msg string) { func (lw *logWrapper) isInVerbosity(minVerb int) bool { return minVerb <= lw.verbosity } + +func (lw *logWrapper) Output(calldepth int, s string) error { + lw.Logv(DebugHigh, s) + return nil +} diff --git a/src/mongo/gotools/mongoreplay/main/mongoreplay.go b/src/mongo/gotools/mongoreplay/main/mongoreplay.go index 1fc09b1fa79..84df7204c01 100644 --- a/src/mongo/gotools/mongoreplay/main/mongoreplay.go +++ b/src/mongo/gotools/mongoreplay/main/mongoreplay.go @@ -8,6 +8,7 @@ package main import ( "github.com/jessevdk/go-flags" + "github.com/mongodb/mongo-tools/common/options" "github.com/mongodb/mongo-tools/mongoreplay" "fmt" @@ -44,11 +45,18 @@ func main() { var parser = flags.NewParser(&opts, flags.Default) - _, err = parser.AddCommand("play", "Play captured traffic against a mongodb instance", "", - &mongoreplay.PlayCommand{GlobalOpts: &opts}) + playCmd := &mongoreplay.PlayCommand{GlobalOpts: &opts} + playCmdParser, err := parser.AddCommand("play", "Play captured traffic against a mongodb instance", "", playCmd) if err != nil { panic(err) } + if options.BuiltWithSSL { + playCmd.SSLOpts = &options.SSL{} + _, err := playCmdParser.AddGroup("ssl", "", playCmd.SSLOpts) + if err != nil { + panic(err) + } + } _, err = parser.AddCommand("record", "Convert network traffic into mongodb queries", "", &mongoreplay.RecordCommand{GlobalOpts: &opts}) diff --git a/src/mongo/gotools/mongoreplay/mongoreplay.go b/src/mongo/gotools/mongoreplay/mongoreplay.go index 9379a967652..14373b3705f 100644 --- a/src/mongo/gotools/mongoreplay/mongoreplay.go +++ b/src/mongo/gotools/mongoreplay/mongoreplay.go @@ -6,6 +6,10 @@ package mongoreplay +import ( + mgo "github.com/10gen/llmgo" +) + // Options stores settings for any mongoreplay command type Options struct { Verbosity []bool `short:"v" long:"verbosity" description:"increase the detail regarding the tools performance on the input file that is output to logs (include multiple times for increased logging verbosity, e.g. -vvv)"` @@ -26,6 +30,10 @@ func (opts *Options) SetLogging() { if d > 0 || v > 0 { printVersionInfo() } + if d == DebugHigh { + mgo.SetLogger(toolDebugLogger) + mgo.SetDebug(true) + } } type VersionOptions struct { diff --git a/src/mongo/gotools/mongoreplay/mongoreplay_test.go b/src/mongo/gotools/mongoreplay/mongoreplay_test.go index 693f23652c8..b43c768ad43 100644 --- a/src/mongo/gotools/mongoreplay/mongoreplay_test.go +++ b/src/mongo/gotools/mongoreplay/mongoreplay_test.go @@ -476,7 +476,7 @@ func comparePayloadType1(t *testing.T, p1, p2 interface{}) { t.Errorf("Payload sizes not matched Saw: %d --- Expected: %d", p1AsPayload.Size, p2AsPayload.Size) } if p1AsPayload.Identifier != p2AsPayload.Identifier { - t.Errorf("Payload identifiers not matched Saw: %d --- Expected: %d", p1AsPayload.Identifier, p2AsPayload.Identifier) + t.Errorf("Payload identifiers not matched Saw: %s --- Expected: %s", p1AsPayload.Identifier, p2AsPayload.Identifier) } } diff --git a/src/mongo/gotools/mongoreplay/play.go b/src/mongo/gotools/mongoreplay/play.go index b2a617c5db4..237127d38ed 100644 --- a/src/mongo/gotools/mongoreplay/play.go +++ b/src/mongo/gotools/mongoreplay/play.go @@ -9,24 +9,27 @@ package mongoreplay import ( "fmt" "io" + "strings" "time" - mgo "github.com/10gen/llmgo" + "github.com/mongodb/mongo-tools/common/lldb" + "github.com/mongodb/mongo-tools/common/options" ) // PlayCommand stores settings for the mongoreplay 'play' subcommand type PlayCommand struct { GlobalOpts *Options `no-flag:"true"` StatOptions - PlaybackFile string `description:"path to the playback file to play from" short:"p" long:"playback-file" required:"yes"` - Speed float64 `description:"multiplier for playback speed (1.0 = real-time, .5 = half-speed, 3.0 = triple-speed, etc.)" long:"speed" default:"1.0"` - URL string `short:"h" long:"host" env:"MONGOREPLAY_HOST" description:"Location of the host to play back against" default:"mongodb://localhost:27017"` - Repeat int `long:"repeat" description:"Number of times to play the playback file" default:"1"` - QueueTime int `long:"queueTime" description:"don't queue ops much further in the future than this number of seconds" default:"15"` - NoPreprocess bool `long:"no-preprocess" description:"don't preprocess the input file to premap data such as mongo cursorIDs"` - Gzip bool `long:"gzip" description:"decompress gzipped input"` - Collect string `long:"collect" description:"Stat collection format; 'format' option uses the --format string" choice:"json" choice:"format" choice:"none" default:"none"` - FullSpeed bool `long:"fullSpeed" description:"run the playback as fast as possible"` + PlaybackFile string `description:"path to the playback file to play from" short:"p" long:"playback-file" required:"yes"` + Speed float64 `description:"multiplier for playback speed (1.0 = real-time, .5 = half-speed, 3.0 = triple-speed, etc.)" long:"speed" default:"1.0"` + URL string `short:"h" long:"host" env:"MONGOREPLAY_HOST" description:"Location of the host to play back against" default:"mongodb://localhost:27017"` + Repeat int `long:"repeat" description:"Number of times to play the playback file" default:"1"` + QueueTime int `long:"queueTime" description:"don't queue ops much further in the future than this number of seconds" default:"15"` + NoPreprocess bool `long:"no-preprocess" description:"don't preprocess the input file to premap data such as mongo cursorIDs"` + Gzip bool `long:"gzip" description:"decompress gzipped input"` + Collect string `long:"collect" description:"Stat collection format; 'format' option uses the --format string" choice:"json" choice:"format" choice:"none" default:"none"` + FullSpeed bool `long:"fullSpeed" description:"run the playback as fast as possible"` + SSLOpts *options.SSL `no-flag:"true"` } const queueGranularity = 1000 @@ -68,7 +71,28 @@ func (play *PlayCommand) Execute(args []string) error { return err } - session, err := mgo.Dial(play.URL) + // Reparse given host via ToolOptions so we can use a SessionProvider + // for the llmgo session. + toolOpts := options.New("", "", options.EnabledOptions{Connection: true, URI: true, Auth: true}) + // SSL options must be non-nil before parsing to enable parsing ssl; + // play.SSLopts will be nil if SSL is not enabled + toolOpts.SSL = play.SSLOpts + if !(strings.HasPrefix(play.URL, "mongodb://") || strings.HasPrefix(play.URL, "mongodb+srv://")) { + play.URL = fmt.Sprintf("mongodb://%s", play.URL) + } + _, err = toolOpts.ParseArgs([]string{"--uri", play.URL}) + + if err != nil { + return err + } + + sp, err := lldb.NewSessionProvider(*toolOpts) + if err != nil { + return err + } + + userInfoLogger.Logv(DebugLow, "Initializing a session") + session, err := sp.GetSession() if err != nil { return err } diff --git a/src/mongo/gotools/mongoreplay/stat_format.go b/src/mongo/gotools/mongoreplay/stat_format.go index 8360b6aece2..25125e8ea88 100644 --- a/src/mongo/gotools/mongoreplay/stat_format.go +++ b/src/mongo/gotools/mongoreplay/stat_format.go @@ -34,10 +34,10 @@ type OpStat struct { Ns string `json:"ns,omitempty"` // Data represents the payload of the request operation. - RequestData interface{} `json:"request_data, omitempty"` + RequestData interface{} `json:"request_data,omitempty"` // Data represents the payload of the reply operation. - ReplyData interface{} `json:"reply_data, omitempty"` + ReplyData interface{} `json:"reply_data,omitempty"` // NumReturned is the number of documents that were fetched as a result of this operation. NumReturned int `json:"nreturned,omitempty"` @@ -77,7 +77,7 @@ type OpStat struct { // RequestID is the ID of the mongodb operation as taken from the header. // The RequestID for a request operation is the same as the ResponseID for // the corresponding reply, so this field will be the same for request/reply pairs. - RequestID int32 `json:"request_id, omitempty"` + RequestID int32 `json:"request_id,omitempty"` } // jsonGet retrieves serialized json req/res via the channel-like arg; diff --git a/src/mongo/gotools/vendor/src/github.com/10gen/llmgo/auth.go b/src/mongo/gotools/vendor/src/github.com/10gen/llmgo/auth.go index 880ba1aa358..70ac345677d 100644 --- a/src/mongo/gotools/vendor/src/github.com/10gen/llmgo/auth.go +++ b/src/mongo/gotools/vendor/src/github.com/10gen/llmgo/auth.go @@ -188,12 +188,12 @@ func (socket *MongoSocket) loginClassic(cred Credential) error { // Note that this only works properly because this function is // synchronous, which means the nonce won't get reset while we're // using it and any other login requests will block waiting for a - // new nonce provided in the defer call below. + // new nonce. + socket.resetNonce(); nonce, err := socket.getNonce() if err != nil { return err } - defer socket.resetNonce() psum := md5.New() psum.Write([]byte(cred.Username + ":mongo:" + cred.Password)) diff --git a/src/mongo/gotools/vendor/src/github.com/10gen/llmgo/session.go b/src/mongo/gotools/vendor/src/github.com/10gen/llmgo/session.go index 636059031c3..b1b82f04510 100644 --- a/src/mongo/gotools/vendor/src/github.com/10gen/llmgo/session.go +++ b/src/mongo/gotools/vendor/src/github.com/10gen/llmgo/session.go @@ -4225,7 +4225,7 @@ func (s *Session) AcquireSocketPrivate(slaveOk bool) (*MongoSocket, error) { } func (s *Session) AcquireSocketDirect() (*MongoSocket, error) { - sock, err := s.cluster().AcquireSocket(Strong, true, s.syncTimeout, s.sockTimeout, s.queryConfig.op.ServerTags, s.poolLimit) + sock, err := s.cluster().AcquireSocket(Strong, false, s.syncTimeout, s.sockTimeout, s.queryConfig.op.ServerTags, s.poolLimit) if err != nil { return nil, err } diff --git a/src/mongo/gotools/vendor/src/github.com/10gen/llmgo/socket.go b/src/mongo/gotools/vendor/src/github.com/10gen/llmgo/socket.go index 0e8980ba199..87e546cc8ec 100644 --- a/src/mongo/gotools/vendor/src/github.com/10gen/llmgo/socket.go +++ b/src/mongo/gotools/vendor/src/github.com/10gen/llmgo/socket.go @@ -322,7 +322,6 @@ func NewSocket(server *MongoServer, conn net.Conn, timeout time.Duration) *Mongo } stats.socketsAlive(+1) debugf("Socket %p to %s: initialized", socket, socket.addr) - socket.resetNonce() go socket.readLoop() return socket } |