diff --git a/.evergreen/config.yml b/.evergreen/config.yml index fda686431..fc1713a88 100644 --- a/.evergreen/config.yml +++ b/.evergreen/config.yml @@ -520,6 +520,18 @@ functions: args: - .evergreen/run-mongodb-oidc-test.sh + "run oidc k8s auth test": + - command: subprocess.exec + type: test + params: + binary: bash + working_dir: src + env: + OIDC_ENV: k8s + include_expansions_in_env: ["DRIVERS_TOOLS", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN", "K8S_VARIANT"] + args: + - ${PROJECT_DIRECTORY}/.evergreen/run-mongodb-oidc-remote-test.sh + "run aws auth test with aws credentials as environment variables": - command: shell.exec type: test @@ -873,6 +885,32 @@ task_groups: tasks: - oidc-auth-test-gcp + - name: testk8soidc_task_group + setup_group: + - func: fetch source + - func: prepare resources + - func: fix absolute paths + - func: make files executable + - command: ec2.assume_role + params: + role_arn: ${aws_test_secrets_role} + duration_seconds: 1800 + - command: subprocess.exec + params: + binary: bash + args: + - ${DRIVERS_TOOLS}/.evergreen/auth_oidc/k8s/setup.sh + teardown_task: + - command: subprocess.exec + params: + binary: bash + args: + - ${DRIVERS_TOOLS}/.evergreen/auth_oidc/k8s/teardown.sh + setup_group_can_fail_task: true + setup_group_timeout_secs: 1800 + tasks: + - oidc-auth-test-k8s + - name: testoidc_task_group setup_group: - func: fetch source @@ -1548,40 +1586,41 @@ tasks: - name: "oidc-auth-test-azure" commands: - - command: shell.exec + - command: subprocess.exec type: test params: - shell: bash - script: |- - set -o errexit - . src/.evergreen/scripts/env.sh - cd src - git add . - git commit -m "add files" - export AZUREOIDC_DRIVERS_TAR_FILE=/tmp/mongo-python-driver.tgz - git archive -o $AZUREOIDC_DRIVERS_TAR_FILE HEAD - export AZUREOIDC_TEST_CMD="OIDC_ENV=azure ./.evergreen/run-mongodb-oidc-test.sh" - bash $DRIVERS_TOOLS/.evergreen/auth_oidc/azure/run-driver-test.sh + binary: bash + working_dir: src + env: + OIDC_ENV: azure + include_expansions_in_env: ["DRIVERS_TOOLS"] + args: + - ${PROJECT_DIRECTORY}/.evergreen/run-mongodb-oidc-remote-test.sh - name: "oidc-auth-test-gcp" commands: - - command: shell.exec + - command: subprocess.exec type: test params: - shell: bash - script: |- - set -o errexit - . src/.evergreen/scripts/env.sh - cd src - git add . - git commit -m "add files" - export GCPOIDC_DRIVERS_TAR_FILE=/tmp/mongo-python-driver.tgz - git archive -o $GCPOIDC_DRIVERS_TAR_FILE HEAD - # Define the command to run on the VM. - # Ensure that we source the environment file created for us, set up any other variables we need, - # and then run our test suite on the vm. - export GCPOIDC_TEST_CMD="OIDC_ENV=gcp ./.evergreen/run-mongodb-oidc-test.sh" - bash $DRIVERS_TOOLS/.evergreen/auth_oidc/gcp/run-driver-test.sh + binary: bash + working_dir: src + env: + OIDC_ENV: gcp + include_expansions_in_env: ["DRIVERS_TOOLS"] + args: + - ${PROJECT_DIRECTORY}/.evergreen/run-mongodb-oidc-remote-test.sh + + - name: "oidc-auth-test-k8s" + commands: + - func: "run oidc k8s auth test" + vars: + K8S_VARIANT: eks + - func: "run oidc k8s auth test" + vars: + K8S_VARIANT: gke + - func: "run oidc k8s auth test" + vars: + K8S_VARIANT: aks # }}} - name: "coverage-report" tags: ["coverage"] @@ -1727,7 +1766,7 @@ tasks: buildvariants: - name: "no-server" - display_name: "No server test" + display_name: "No server" run_on: - rhel84-small tasks: @@ -1740,45 +1779,26 @@ buildvariants: tasks: - name: "coverage-report" -- name: testazureoidc-variant - display_name: "OIDC Auth Azure" - run_on: ubuntu2204-small - tasks: - - name: testazureoidc_task_group - batchtime: 20160 # Use a batchtime of 14 days as suggested by the CSFLE test README - -- name: testgcpoidc-variant - display_name: "OIDC Auth GCP" - run_on: ubuntu2204-small - tasks: - - name: testgcpoidc_task_group - batchtime: 20160 # Use a batchtime of 14 days as suggested by the CSFLE test README - -- name: testgcpkms-variant - display_name: "GCP KMS" +- name: testkms-variant + display_name: "KMS" run_on: - debian11-small tasks: - name: testgcpkms_task_group batchtime: 20160 # Use a batchtime of 14 days as suggested by the CSFLE test README - testgcpkms-fail-task - -- name: testazurekms-variant - display_name: "Azure KMS" - run_on: debian11-small - tasks: - name: testazurekms_task_group batchtime: 20160 # Use a batchtime of 14 days as suggested by the CSFLE test README - testazurekms-fail-task - name: rhel8-test-lambda - display_name: AWS Lambda handler tests + display_name: FaaS Lambda run_on: rhel87-small tasks: - name: test_aws_lambda_task_group - name: rhel8-import-time - display_name: Import Time Check + display_name: Import Time run_on: rhel87-small tasks: - name: "check-import-time" @@ -1791,7 +1811,7 @@ buildvariants: - name: "backport-pr" - name: "perf-tests" - display_name: "Performance Benchmark Tests" + display_name: "Performance Benchmarks" batchtime: 10080 # 7 days run_on: rhel90-dbx-perf-large tasks: diff --git a/.evergreen/generated_configs/variants.yml b/.evergreen/generated_configs/variants.yml index 0a4e5cfb1..9ee51899f 100644 --- a/.evergreen/generated_configs/variants.yml +++ b/.evergreen/generated_configs/variants.yml @@ -106,7 +106,7 @@ buildvariants: PYTHON_BINARY: /opt/python/3.13/bin/python3 # Aws auth tests - - name: aws-auth-ubuntu-20-py3.9 + - name: auth-aws-ubuntu-20-py3.9 tasks: - name: aws-auth-test-4.4 - name: aws-auth-test-5.0 @@ -115,12 +115,12 @@ buildvariants: - name: aws-auth-test-8.0 - name: aws-auth-test-rapid - name: aws-auth-test-latest - display_name: AWS Auth Ubuntu-20 py3.9 + display_name: Auth AWS Ubuntu-20 py3.9 run_on: - ubuntu2004-small expansions: PYTHON_BINARY: /opt/python/3.9/bin/python3 - - name: aws-auth-ubuntu-20-py3.13 + - name: auth-aws-ubuntu-20-py3.13 tasks: - name: aws-auth-test-4.4 - name: aws-auth-test-5.0 @@ -129,12 +129,12 @@ buildvariants: - name: aws-auth-test-8.0 - name: aws-auth-test-rapid - name: aws-auth-test-latest - display_name: AWS Auth Ubuntu-20 py3.13 + display_name: Auth AWS Ubuntu-20 py3.13 run_on: - ubuntu2004-small expansions: PYTHON_BINARY: /opt/python/3.13/bin/python3 - - name: aws-auth-win64-py3.9 + - name: auth-aws-win64-py3.9 tasks: - name: aws-auth-test-4.4 - name: aws-auth-test-5.0 @@ -143,13 +143,13 @@ buildvariants: - name: aws-auth-test-8.0 - name: aws-auth-test-rapid - name: aws-auth-test-latest - display_name: AWS Auth Win64 py3.9 + display_name: Auth AWS Win64 py3.9 run_on: - windows-64-vsMulti-small expansions: skip_ECS_auth_test: "true" PYTHON_BINARY: C:/python/Python39/python.exe - - name: aws-auth-win64-py3.13 + - name: auth-aws-win64-py3.13 tasks: - name: aws-auth-test-4.4 - name: aws-auth-test-5.0 @@ -158,13 +158,13 @@ buildvariants: - name: aws-auth-test-8.0 - name: aws-auth-test-rapid - name: aws-auth-test-latest - display_name: AWS Auth Win64 py3.13 + display_name: Auth AWS Win64 py3.13 run_on: - windows-64-vsMulti-small expansions: skip_ECS_auth_test: "true" PYTHON_BINARY: C:/python/Python313/python.exe - - name: aws-auth-macos-py3.9 + - name: auth-aws-macos-py3.9 tasks: - name: aws-auth-test-4.4 - name: aws-auth-test-5.0 @@ -173,7 +173,7 @@ buildvariants: - name: aws-auth-test-8.0 - name: aws-auth-test-rapid - name: aws-auth-test-latest - display_name: AWS Auth macOS py3.9 + display_name: Auth AWS macOS py3.9 run_on: - macos-14 expansions: @@ -181,7 +181,7 @@ buildvariants: skip_EC2_auth_test: "true" skip_web_identity_auth_test: "true" PYTHON_BINARY: /Library/Frameworks/Python.Framework/Versions/3.9/bin/python3 - - name: aws-auth-macos-py3.13 + - name: auth-aws-macos-py3.13 tasks: - name: aws-auth-test-4.4 - name: aws-auth-test-5.0 @@ -190,7 +190,7 @@ buildvariants: - name: aws-auth-test-8.0 - name: aws-auth-test-rapid - name: aws-auth-test-latest - display_name: AWS Auth macOS py3.13 + display_name: Auth AWS macOS py3.13 run_on: - macos-14 expansions: @@ -200,85 +200,85 @@ buildvariants: PYTHON_BINARY: /Library/Frameworks/Python.Framework/Versions/3.13/bin/python3 # Compression tests - - name: snappy-compression-rhel8-py3.9-no-c + - name: compression-snappy-rhel8-py3.9-no-c tasks: - name: .standalone .noauth .nossl .sync_async - display_name: snappy compression RHEL8 py3.9 No C + display_name: Compression snappy RHEL8 py3.9 No C run_on: - rhel87-small expansions: COMPRESSORS: snappy NO_EXT: "1" PYTHON_BINARY: /opt/python/3.9/bin/python3 - - name: snappy-compression-rhel8-py3.10 + - name: compression-snappy-rhel8-py3.10 tasks: - name: .standalone .noauth .nossl .sync_async - display_name: snappy compression RHEL8 py3.10 + display_name: Compression snappy RHEL8 py3.10 run_on: - rhel87-small expansions: COMPRESSORS: snappy PYTHON_BINARY: /opt/python/3.10/bin/python3 - - name: zlib-compression-rhel8-py3.11-no-c + - name: compression-zlib-rhel8-py3.11-no-c tasks: - name: .standalone .noauth .nossl .sync_async - display_name: zlib compression RHEL8 py3.11 No C + display_name: Compression zlib RHEL8 py3.11 No C run_on: - rhel87-small expansions: COMPRESSORS: zlib NO_EXT: "1" PYTHON_BINARY: /opt/python/3.11/bin/python3 - - name: zlib-compression-rhel8-py3.12 + - name: compression-zlib-rhel8-py3.12 tasks: - name: .standalone .noauth .nossl .sync_async - display_name: zlib compression RHEL8 py3.12 + display_name: Compression zlib RHEL8 py3.12 run_on: - rhel87-small expansions: COMPRESSORS: zlib PYTHON_BINARY: /opt/python/3.12/bin/python3 - - name: zstd-compression-rhel8-py3.13-no-c + - name: compression-zstd-rhel8-py3.13-no-c tasks: - name: .standalone .noauth .nossl .sync_async !.4.0 - display_name: zstd compression RHEL8 py3.13 No C + display_name: Compression zstd RHEL8 py3.13 No C run_on: - rhel87-small expansions: COMPRESSORS: zstd NO_EXT: "1" PYTHON_BINARY: /opt/python/3.13/bin/python3 - - name: zstd-compression-rhel8-py3.9 + - name: compression-zstd-rhel8-py3.9 tasks: - name: .standalone .noauth .nossl .sync_async !.4.0 - display_name: zstd compression RHEL8 py3.9 + display_name: Compression zstd RHEL8 py3.9 run_on: - rhel87-small expansions: COMPRESSORS: zstd PYTHON_BINARY: /opt/python/3.9/bin/python3 - - name: snappy-compression-rhel8-pypy3.9 + - name: compression-snappy-rhel8-pypy3.9 tasks: - name: .standalone .noauth .nossl .sync_async - display_name: snappy compression RHEL8 pypy3.9 + display_name: Compression snappy RHEL8 pypy3.9 run_on: - rhel87-small expansions: COMPRESSORS: snappy PYTHON_BINARY: /opt/python/pypy3.9/bin/python3 - - name: zlib-compression-rhel8-pypy3.10 + - name: compression-zlib-rhel8-pypy3.10 tasks: - name: .standalone .noauth .nossl .sync_async - display_name: zlib compression RHEL8 pypy3.10 + display_name: Compression zlib RHEL8 pypy3.10 run_on: - rhel87-small expansions: COMPRESSORS: zlib PYTHON_BINARY: /opt/python/pypy3.10/bin/python3 - - name: zstd-compression-rhel8-pypy3.9 + - name: compression-zstd-rhel8-pypy3.9 tasks: - name: .standalone .noauth .nossl .sync_async !.4.0 - display_name: zstd compression RHEL8 pypy3.9 + display_name: Compression zstd RHEL8 pypy3.9 run_on: - rhel87-small expansions: @@ -564,64 +564,64 @@ buildvariants: tags: [encryption_tag] # Enterprise auth tests - - name: enterprise-auth-macos-py3.9-auth + - name: auth-enterprise-macos-py3.9-auth tasks: - name: test-enterprise-auth - display_name: Enterprise Auth macOS py3.9 Auth + display_name: Auth Enterprise macOS py3.9 Auth run_on: - macos-14 expansions: AUTH: auth PYTHON_BINARY: /Library/Frameworks/Python.Framework/Versions/3.9/bin/python3 - - name: enterprise-auth-rhel8-py3.10-auth + - name: auth-enterprise-rhel8-py3.10-auth tasks: - name: test-enterprise-auth - display_name: Enterprise Auth RHEL8 py3.10 Auth + display_name: Auth Enterprise RHEL8 py3.10 Auth run_on: - rhel87-small expansions: AUTH: auth PYTHON_BINARY: /opt/python/3.10/bin/python3 - - name: enterprise-auth-rhel8-py3.11-auth + - name: auth-enterprise-rhel8-py3.11-auth tasks: - name: test-enterprise-auth - display_name: Enterprise Auth RHEL8 py3.11 Auth + display_name: Auth Enterprise RHEL8 py3.11 Auth run_on: - rhel87-small expansions: AUTH: auth PYTHON_BINARY: /opt/python/3.11/bin/python3 - - name: enterprise-auth-rhel8-py3.12-auth + - name: auth-enterprise-rhel8-py3.12-auth tasks: - name: test-enterprise-auth - display_name: Enterprise Auth RHEL8 py3.12 Auth + display_name: Auth Enterprise RHEL8 py3.12 Auth run_on: - rhel87-small expansions: AUTH: auth PYTHON_BINARY: /opt/python/3.12/bin/python3 - - name: enterprise-auth-win64-py3.13-auth + - name: auth-enterprise-win64-py3.13-auth tasks: - name: test-enterprise-auth - display_name: Enterprise Auth Win64 py3.13 Auth + display_name: Auth Enterprise Win64 py3.13 Auth run_on: - windows-64-vsMulti-small expansions: AUTH: auth PYTHON_BINARY: C:/python/Python313/python.exe - - name: enterprise-auth-rhel8-pypy3.9-auth + - name: auth-enterprise-rhel8-pypy3.9-auth tasks: - name: test-enterprise-auth - display_name: Enterprise Auth RHEL8 pypy3.9 Auth + display_name: Auth Enterprise RHEL8 pypy3.9 Auth run_on: - rhel87-small expansions: AUTH: auth PYTHON_BINARY: /opt/python/pypy3.9/bin/python3 - - name: enterprise-auth-rhel8-pypy3.10-auth + - name: auth-enterprise-rhel8-pypy3.10-auth tasks: - name: test-enterprise-auth - display_name: Enterprise Auth RHEL8 pypy3.10 Auth + display_name: Auth Enterprise RHEL8 pypy3.10 Auth run_on: - rhel87-small expansions: @@ -629,10 +629,10 @@ buildvariants: PYTHON_BINARY: /opt/python/pypy3.10/bin/python3 # Green framework tests - - name: eventlet-rhel8-py3.9 + - name: green-eventlet-rhel8-py3.9 tasks: - name: .standalone .noauth .nossl .sync_async - display_name: Eventlet RHEL8 py3.9 + display_name: Green Eventlet RHEL8 py3.9 run_on: - rhel87-small expansions: @@ -640,10 +640,10 @@ buildvariants: AUTH: auth SSL: ssl PYTHON_BINARY: /opt/python/3.9/bin/python3 - - name: gevent-rhel8-py3.9 + - name: green-gevent-rhel8-py3.9 tasks: - name: .standalone .noauth .nossl .sync_async - display_name: Gevent RHEL8 py3.9 + display_name: Green Gevent RHEL8 py3.9 run_on: - rhel87-small expansions: @@ -651,10 +651,10 @@ buildvariants: AUTH: auth SSL: ssl PYTHON_BINARY: /opt/python/3.9/bin/python3 - - name: eventlet-rhel8-py3.12 + - name: green-eventlet-rhel8-py3.12 tasks: - name: .standalone .noauth .nossl .sync_async - display_name: Eventlet RHEL8 py3.12 + display_name: Green Eventlet RHEL8 py3.12 run_on: - rhel87-small expansions: @@ -662,10 +662,10 @@ buildvariants: AUTH: auth SSL: ssl PYTHON_BINARY: /opt/python/3.12/bin/python3 - - name: gevent-rhel8-py3.12 + - name: green-gevent-rhel8-py3.12 tasks: - name: .standalone .noauth .nossl .sync_async - display_name: Gevent RHEL8 py3.12 + display_name: Green Gevent RHEL8 py3.12 run_on: - rhel87-small expansions: @@ -727,10 +727,10 @@ buildvariants: VERSION: latest # Mockupdb tests - - name: mockupdb-tests-rhel8-py3.9 + - name: mockupdb-rhel8-py3.9 tasks: - name: mockupdb - display_name: MockupDB Tests RHEL8 py3.9 + display_name: MockupDB RHEL8 py3.9 run_on: - rhel87-small expansions: @@ -810,10 +810,10 @@ buildvariants: PYTHON_BINARY: /opt/python/3.13/bin/python3 # Ocsp tests - - name: ocsp-test-rhel8-v4.4-py3.9 + - name: ocsp-rhel8-v4.4-py3.9 tasks: - name: .ocsp - display_name: OCSP test RHEL8 v4.4 py3.9 + display_name: OCSP RHEL8 v4.4 py3.9 run_on: - rhel87-small batchtime: 20160 @@ -823,10 +823,10 @@ buildvariants: TOPOLOGY: server PYTHON_BINARY: /opt/python/3.9/bin/python3 VERSION: "4.4" - - name: ocsp-test-rhel8-v5.0-py3.10 + - name: ocsp-rhel8-v5.0-py3.10 tasks: - name: .ocsp - display_name: OCSP test RHEL8 v5.0 py3.10 + display_name: OCSP RHEL8 v5.0 py3.10 run_on: - rhel87-small batchtime: 20160 @@ -836,10 +836,10 @@ buildvariants: TOPOLOGY: server PYTHON_BINARY: /opt/python/3.10/bin/python3 VERSION: "5.0" - - name: ocsp-test-rhel8-v6.0-py3.11 + - name: ocsp-rhel8-v6.0-py3.11 tasks: - name: .ocsp - display_name: OCSP test RHEL8 v6.0 py3.11 + display_name: OCSP RHEL8 v6.0 py3.11 run_on: - rhel87-small batchtime: 20160 @@ -849,10 +849,10 @@ buildvariants: TOPOLOGY: server PYTHON_BINARY: /opt/python/3.11/bin/python3 VERSION: "6.0" - - name: ocsp-test-rhel8-v7.0-py3.12 + - name: ocsp-rhel8-v7.0-py3.12 tasks: - name: .ocsp - display_name: OCSP test RHEL8 v7.0 py3.12 + display_name: OCSP RHEL8 v7.0 py3.12 run_on: - rhel87-small batchtime: 20160 @@ -862,10 +862,10 @@ buildvariants: TOPOLOGY: server PYTHON_BINARY: /opt/python/3.12/bin/python3 VERSION: "7.0" - - name: ocsp-test-rhel8-v8.0-py3.13 + - name: ocsp-rhel8-v8.0-py3.13 tasks: - name: .ocsp - display_name: OCSP test RHEL8 v8.0 py3.13 + display_name: OCSP RHEL8 v8.0 py3.13 run_on: - rhel87-small batchtime: 20160 @@ -875,10 +875,10 @@ buildvariants: TOPOLOGY: server PYTHON_BINARY: /opt/python/3.13/bin/python3 VERSION: "8.0" - - name: ocsp-test-rhel8-rapid-pypy3.9 + - name: ocsp-rhel8-rapid-pypy3.9 tasks: - name: .ocsp - display_name: OCSP test RHEL8 rapid pypy3.9 + display_name: OCSP RHEL8 rapid pypy3.9 run_on: - rhel87-small batchtime: 20160 @@ -888,10 +888,10 @@ buildvariants: TOPOLOGY: server PYTHON_BINARY: /opt/python/pypy3.9/bin/python3 VERSION: rapid - - name: ocsp-test-rhel8-latest-pypy3.10 + - name: ocsp-rhel8-latest-pypy3.10 tasks: - name: .ocsp - display_name: OCSP test RHEL8 latest pypy3.10 + display_name: OCSP RHEL8 latest pypy3.10 run_on: - rhel87-small batchtime: 20160 @@ -901,10 +901,10 @@ buildvariants: TOPOLOGY: server PYTHON_BINARY: /opt/python/pypy3.10/bin/python3 VERSION: latest - - name: ocsp-test-win64-v4.4-py3.9 + - name: ocsp-win64-v4.4-py3.9 tasks: - name: .ocsp-rsa !.ocsp-staple - display_name: OCSP test Win64 v4.4 py3.9 + display_name: OCSP Win64 v4.4 py3.9 run_on: - windows-64-vsMulti-small batchtime: 20160 @@ -914,10 +914,10 @@ buildvariants: TOPOLOGY: server PYTHON_BINARY: C:/python/Python39/python.exe VERSION: "4.4" - - name: ocsp-test-win64-v8.0-py3.13 + - name: ocsp-win64-v8.0-py3.13 tasks: - name: .ocsp-rsa !.ocsp-staple - display_name: OCSP test Win64 v8.0 py3.13 + display_name: OCSP Win64 v8.0 py3.13 run_on: - windows-64-vsMulti-small batchtime: 20160 @@ -927,10 +927,10 @@ buildvariants: TOPOLOGY: server PYTHON_BINARY: C:/python/Python313/python.exe VERSION: "8.0" - - name: ocsp-test-macos-v4.4-py3.9 + - name: ocsp-macos-v4.4-py3.9 tasks: - name: .ocsp-rsa !.ocsp-staple - display_name: OCSP test macOS v4.4 py3.9 + display_name: OCSP macOS v4.4 py3.9 run_on: - macos-14 batchtime: 20160 @@ -940,10 +940,10 @@ buildvariants: TOPOLOGY: server PYTHON_BINARY: /Library/Frameworks/Python.Framework/Versions/3.9/bin/python3 VERSION: "4.4" - - name: ocsp-test-macos-v8.0-py3.13 + - name: ocsp-macos-v8.0-py3.13 tasks: - name: .ocsp-rsa !.ocsp-staple - display_name: OCSP test macOS v8.0 py3.13 + display_name: OCSP macOS v8.0 py3.13 run_on: - macos-14 batchtime: 20160 @@ -955,24 +955,27 @@ buildvariants: VERSION: "8.0" # Oidc auth tests - - name: oidc-auth-rhel8 + - name: auth-oidc-ubuntu-22 tasks: - name: testoidc_task_group - display_name: OIDC Auth RHEL8 + - name: testazureoidc_task_group + - name: testgcpoidc_task_group + - name: testk8soidc_task_group + display_name: Auth OIDC Ubuntu-22 run_on: - - rhel87-small + - ubuntu2204-small batchtime: 20160 - - name: oidc-auth-macos + - name: auth-oidc-macos tasks: - name: testoidc_task_group - display_name: OIDC Auth macOS + display_name: Auth OIDC macOS run_on: - macos-14 batchtime: 20160 - - name: oidc-auth-win64 + - name: auth-oidc-win64 tasks: - name: testoidc_task_group - display_name: OIDC Auth Win64 + display_name: Auth OIDC Win64 run_on: - windows-64-vsMulti-small batchtime: 20160 @@ -1072,7 +1075,7 @@ buildvariants: - name: .standalone .sync_async - name: .replica_set .sync_async - name: .sharded_cluster .sync_async - display_name: Test RHEL8 py3.9 cov + display_name: "* Test RHEL8 py3.9 cov" run_on: - rhel87-small expansions: @@ -1084,7 +1087,7 @@ buildvariants: - name: .standalone .sync_async - name: .replica_set .sync_async - name: .sharded_cluster .sync_async - display_name: Test RHEL8 py3.13 cov + display_name: "* Test RHEL8 py3.13 cov" run_on: - rhel87-small expansions: @@ -1096,7 +1099,7 @@ buildvariants: - name: .standalone .sync_async - name: .replica_set .sync_async - name: .sharded_cluster .sync_async - display_name: Test RHEL8 pypy3.10 cov + display_name: "* Test RHEL8 pypy3.10 cov" run_on: - rhel87-small expansions: @@ -1108,7 +1111,7 @@ buildvariants: - name: .sharded_cluster .auth .ssl .sync_async - name: .replica_set .noauth .ssl .sync_async - name: .standalone .noauth .nossl .sync_async - display_name: Test RHEL8 py3.10 + display_name: "* Test RHEL8 py3.10" run_on: - rhel87-small expansions: @@ -1119,7 +1122,7 @@ buildvariants: - name: .sharded_cluster .auth .ssl .sync_async - name: .replica_set .noauth .ssl .sync_async - name: .standalone .noauth .nossl .sync_async - display_name: Test RHEL8 py3.11 + display_name: "* Test RHEL8 py3.11" run_on: - rhel87-small expansions: @@ -1130,7 +1133,7 @@ buildvariants: - name: .sharded_cluster .auth .ssl .sync_async - name: .replica_set .noauth .ssl .sync_async - name: .standalone .noauth .nossl .sync_async - display_name: Test RHEL8 py3.12 + display_name: "* Test RHEL8 py3.12" run_on: - rhel87-small expansions: @@ -1141,7 +1144,7 @@ buildvariants: - name: .sharded_cluster .auth .ssl .sync_async - name: .replica_set .noauth .ssl .sync_async - name: .standalone .noauth .nossl .sync_async - display_name: Test RHEL8 pypy3.9 + display_name: "* Test RHEL8 pypy3.9" run_on: - rhel87-small expansions: @@ -1152,7 +1155,7 @@ buildvariants: - name: .sharded_cluster .auth .ssl !.sync_async - name: .replica_set .noauth .ssl !.sync_async - name: .standalone .noauth .nossl !.sync_async - display_name: Test macOS py3.9 + display_name: "* Test macOS py3.9" run_on: - macos-14 expansions: @@ -1163,7 +1166,7 @@ buildvariants: - name: .sharded_cluster .auth .ssl !.sync_async - name: .replica_set .noauth .ssl !.sync_async - name: .standalone .noauth .nossl !.sync_async - display_name: Test macOS py3.13 + display_name: "* Test macOS py3.13" run_on: - macos-14 expansions: @@ -1186,7 +1189,7 @@ buildvariants: - name: .sharded_cluster .auth .ssl .latest !.sync_async - name: .replica_set .noauth .ssl .latest !.sync_async - name: .standalone .noauth .nossl .latest !.sync_async - display_name: Test macOS Arm64 py3.9 + display_name: "* Test macOS Arm64 py3.9" run_on: - macos-14-arm64 expansions: @@ -1209,7 +1212,7 @@ buildvariants: - name: .sharded_cluster .auth .ssl .latest !.sync_async - name: .replica_set .noauth .ssl .latest !.sync_async - name: .standalone .noauth .nossl .latest !.sync_async - display_name: Test macOS Arm64 py3.13 + display_name: "* Test macOS Arm64 py3.13" run_on: - macos-14-arm64 expansions: @@ -1220,7 +1223,7 @@ buildvariants: - name: .sharded_cluster .auth .ssl !.sync_async - name: .replica_set .noauth .ssl !.sync_async - name: .standalone .noauth .nossl !.sync_async - display_name: Test Win64 py3.9 + display_name: "* Test Win64 py3.9" run_on: - windows-64-vsMulti-small expansions: @@ -1231,7 +1234,7 @@ buildvariants: - name: .sharded_cluster .auth .ssl !.sync_async - name: .replica_set .noauth .ssl !.sync_async - name: .standalone .noauth .nossl !.sync_async - display_name: Test Win64 py3.13 + display_name: "* Test Win64 py3.13" run_on: - windows-64-vsMulti-small expansions: @@ -1242,7 +1245,7 @@ buildvariants: - name: .sharded_cluster .auth .ssl !.sync_async - name: .replica_set .noauth .ssl !.sync_async - name: .standalone .noauth .nossl !.sync_async - display_name: Test Win32 py3.9 + display_name: "* Test Win32 py3.9" run_on: - windows-64-vsMulti-small expansions: @@ -1253,7 +1256,7 @@ buildvariants: - name: .sharded_cluster .auth .ssl !.sync_async - name: .replica_set .noauth .ssl !.sync_async - name: .standalone .noauth .nossl !.sync_async - display_name: Test Win32 py3.13 + display_name: "* Test Win32 py3.13" run_on: - windows-64-vsMulti-small expansions: @@ -1285,3 +1288,99 @@ buildvariants: AUTH: auth SSL: ssl PYTHON_BINARY: /opt/python/3.13/bin/python3 + + # Stable api tests + - name: stable-api-require-v1-rhel8-py3.9-auth + tasks: + - name: .standalone .5.0 .noauth .nossl .sync_async + - name: .standalone .6.0 .noauth .nossl .sync_async + - name: .standalone .7.0 .noauth .nossl .sync_async + - name: .standalone .8.0 .noauth .nossl .sync_async + - name: .standalone .rapid .noauth .nossl .sync_async + - name: .standalone .latest .noauth .nossl .sync_async + display_name: Stable API require v1 RHEL8 py3.9 Auth + run_on: + - rhel87-small + expansions: + AUTH: auth + REQUIRE_API_VERSION: "1" + MONGODB_API_VERSION: "1" + PYTHON_BINARY: /opt/python/3.9/bin/python3 + tags: [versionedApi_tag] + - name: stable-api-accept-v2-rhel8-py3.9-auth + tasks: + - name: .standalone .5.0 .noauth .nossl .sync_async + - name: .standalone .6.0 .noauth .nossl .sync_async + - name: .standalone .7.0 .noauth .nossl .sync_async + - name: .standalone .8.0 .noauth .nossl .sync_async + - name: .standalone .rapid .noauth .nossl .sync_async + - name: .standalone .latest .noauth .nossl .sync_async + display_name: Stable API accept v2 RHEL8 py3.9 Auth + run_on: + - rhel87-small + expansions: + AUTH: auth + ORCHESTRATION_FILE: versioned-api-testing.json + PYTHON_BINARY: /opt/python/3.9/bin/python3 + tags: [versionedApi_tag] + - name: stable-api-require-v1-rhel8-py3.13-auth + tasks: + - name: .standalone .5.0 .noauth .nossl .sync_async + - name: .standalone .6.0 .noauth .nossl .sync_async + - name: .standalone .7.0 .noauth .nossl .sync_async + - name: .standalone .8.0 .noauth .nossl .sync_async + - name: .standalone .rapid .noauth .nossl .sync_async + - name: .standalone .latest .noauth .nossl .sync_async + display_name: Stable API require v1 RHEL8 py3.13 Auth + run_on: + - rhel87-small + expansions: + AUTH: auth + REQUIRE_API_VERSION: "1" + MONGODB_API_VERSION: "1" + PYTHON_BINARY: /opt/python/3.13/bin/python3 + tags: [versionedApi_tag] + - name: stable-api-accept-v2-rhel8-py3.13-auth + tasks: + - name: .standalone .5.0 .noauth .nossl .sync_async + - name: .standalone .6.0 .noauth .nossl .sync_async + - name: .standalone .7.0 .noauth .nossl .sync_async + - name: .standalone .8.0 .noauth .nossl .sync_async + - name: .standalone .rapid .noauth .nossl .sync_async + - name: .standalone .latest .noauth .nossl .sync_async + display_name: Stable API accept v2 RHEL8 py3.13 Auth + run_on: + - rhel87-small + expansions: + AUTH: auth + ORCHESTRATION_FILE: versioned-api-testing.json + PYTHON_BINARY: /opt/python/3.13/bin/python3 + tags: [versionedApi_tag] + + # Storage engine tests + - name: storage-inmemory-rhel8-py3.9 + tasks: + - name: .standalone .noauth .nossl .4.0 .sync_async + - name: .standalone .noauth .nossl .4.4 .sync_async + - name: .standalone .noauth .nossl .5.0 .sync_async + - name: .standalone .noauth .nossl .6.0 .sync_async + - name: .standalone .noauth .nossl .7.0 .sync_async + - name: .standalone .noauth .nossl .8.0 .sync_async + - name: .standalone .noauth .nossl .rapid .sync_async + - name: .standalone .noauth .nossl .latest .sync_async + display_name: Storage InMemory RHEL8 py3.9 + run_on: + - rhel87-small + expansions: + STORAGE_ENGINE: inmemory + PYTHON_BINARY: /opt/python/3.9/bin/python3 + - name: storage-mmapv1-rhel8-py3.9 + tasks: + - name: .standalone .4.0 .noauth .nossl .sync_async + - name: .replica_set .4.0 .noauth .nossl .sync_async + display_name: Storage MMAPv1 RHEL8 py3.9 + run_on: + - rhel87-small + expansions: + STORAGE_ENGINE: mmapv1 + PYTHON_BINARY: /opt/python/3.9/bin/python3 diff --git a/.evergreen/run-mongodb-oidc-remote-test.sh b/.evergreen/run-mongodb-oidc-remote-test.sh new file mode 100755 index 000000000..bb90bddf0 --- /dev/null +++ b/.evergreen/run-mongodb-oidc-remote-test.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +set +x # Disable debug trace +set -eu + +echo "Running MONGODB-OIDC remote tests" + +OIDC_ENV=${OIDC_ENV:-"test"} + +# Make sure DRIVERS_TOOLS is set. +if [ -z "$DRIVERS_TOOLS" ]; then + echo "Must specify DRIVERS_TOOLS" + exit 1 +fi + +# Set up the remote files to test. +git add . +git commit -m "add files" || true +export TEST_TAR_FILE=/tmp/mongo-python-driver.tgz +git archive -o $TEST_TAR_FILE HEAD + +pushd $DRIVERS_TOOLS + +if [ $OIDC_ENV == "test" ]; then + echo "Test OIDC environment does not support remote test!" + exit 1 + +elif [ $OIDC_ENV == "azure" ]; then + export AZUREOIDC_DRIVERS_TAR_FILE=$TEST_TAR_FILE + export AZUREOIDC_TEST_CMD="OIDC_ENV=azure ./.evergreen/run-mongodb-oidc-test.sh" + bash ./.evergreen/auth_oidc/azure/run-driver-test.sh + +elif [ $OIDC_ENV == "gcp" ]; then + export GCPOIDC_DRIVERS_TAR_FILE=$TEST_TAR_FILE + export GCPOIDC_TEST_CMD="OIDC_ENV=gcp ./.evergreen/run-mongodb-oidc-test.sh" + bash ./.evergreen/auth_oidc/gcp/run-driver-test.sh + +elif [ $OIDC_ENV == "k8s" ]; then + # Make sure K8S_VARIANT is set. + if [ -z "$K8S_VARIANT" ]; then + echo "Must specify K8S_VARIANT" + popd + exit 1 + fi + + bash ./.evergreen/auth_oidc/k8s/setup-pod.sh + bash ./.evergreen/auth_oidc/k8s/run-self-test.sh + export K8S_DRIVERS_TAR_FILE=$TEST_TAR_FILE + export K8S_TEST_CMD="OIDC_ENV=k8s ./.evergreen/run-mongodb-oidc-test.sh" + source ./.evergreen/auth_oidc/k8s/secrets-export.sh # for MONGODB_URI + bash ./.evergreen/auth_oidc/k8s/run-driver-test.sh + bash ./.evergreen/auth_oidc/k8s/teardown-pod.sh + +else + echo "Unrecognized OIDC_ENV $OIDC_ENV" + pod + exit 1 +fi + +popd diff --git a/.evergreen/run-mongodb-oidc-test.sh b/.evergreen/run-mongodb-oidc-test.sh index 0c34912c8..22864528c 100755 --- a/.evergreen/run-mongodb-oidc-test.sh +++ b/.evergreen/run-mongodb-oidc-test.sh @@ -21,6 +21,9 @@ elif [ $OIDC_ENV == "azure" ]; then elif [ $OIDC_ENV == "gcp" ]; then source ./secrets-export.sh +elif [ $OIDC_ENV == "k8s" ]; then + echo "Running oidc on k8s" + else echo "Unrecognized OIDC_ENV $OIDC_ENV" exit 1 diff --git a/.evergreen/scripts/generate_config.py b/.evergreen/scripts/generate_config.py index 9abcc6516..05529ecb2 100644 --- a/.evergreen/scripts/generate_config.py +++ b/.evergreen/scripts/generate_config.py @@ -93,7 +93,7 @@ def create_variant( else: host = host or "rhel8" run_on = [HOSTS[host].run_on] - name = display_name.replace(" ", "-").lower() + name = display_name.replace(" ", "-").replace("*-", "").lower() if python: expansions["PYTHON_BINARY"] = get_python_binary(python, host) if version: @@ -201,7 +201,7 @@ def create_ocsp_variants() -> list[BuildVariant]: variants = [] batchtime = BATCHTIME_WEEK * 2 expansions = dict(AUTH="noauth", SSL="ssl", TOPOLOGY="server") - base_display = "OCSP test" + base_display = "OCSP" # OCSP tests on rhel8 with all servers v4.4+ and all python versions. versions = [v for v in ALL_VERSIONS if v != "4.0"] @@ -241,10 +241,11 @@ def create_server_variants() -> list[BuildVariant]: # Run the full matrix on linux with min and max CPython, and latest pypy. host = "rhel8" + # Prefix the display name with an asterisk so it is sorted first. + base_display_name = "* Test" for python in [*MIN_MAX_PYTHON, PYPYS[-1]]: - display_name = f"Test {host}" expansions = dict(COVERAGE="coverage") - display_name = get_display_name("Test", host, python=python, **expansions) + display_name = get_display_name(base_display_name, host, python=python, **expansions) variant = create_variant( [f".{t} .sync_async" for t in TOPOLOGIES], display_name, @@ -258,7 +259,7 @@ def create_server_variants() -> list[BuildVariant]: # Test the rest of the pythons. for python in CPYTHONS[1:-1] + PYPYS[:-1]: display_name = f"Test {host}" - display_name = get_display_name("Test", host, python=python) + display_name = get_display_name(base_display_name, host, python=python) variant = create_variant( [f"{t} .sync_async" for t in SUB_TASKS], display_name, @@ -278,7 +279,7 @@ def create_server_variants() -> list[BuildVariant]: for version in get_versions_from("6.0"): tasks.extend(f"{t} .{version} !.sync_async" for t in SUB_TASKS) expansions = dict(SKIP_CSOT_TESTS="true") - display_name = get_display_name("Test", host, python=python, **expansions) + display_name = get_display_name(base_display_name, host, python=python, **expansions) variant = create_variant( tasks, display_name, @@ -385,7 +386,7 @@ def create_compression_variants(): for ind, (compressor, c_ext) in enumerate(product(["snappy", "zlib", "zstd"], C_EXTS)): expansions = dict(COMPRESSORS=compressor) handle_c_ext(c_ext, expansions) - base_name = f"{compressor} compression" + base_name = f"Compression {compressor}" python = CPYTHONS[ind % len(CPYTHONS)] display_name = get_display_name(base_name, host, python=python, **expansions) variant = create_variant( @@ -401,7 +402,7 @@ def create_compression_variants(): for compressor, python in zip_cycle(["snappy", "zlib", "zstd"], other_pythons): expansions = dict(COMPRESSORS=compressor) handle_c_ext(c_ext, expansions) - base_name = f"{compressor} compression" + base_name = f"Compression {compressor}" display_name = get_display_name(base_name, host, python=python, **expansions) variant = create_variant( task_names[compressor], @@ -427,7 +428,7 @@ def create_enterprise_auth_variants(): host = "win64" else: host = "rhel8" - display_name = get_display_name("Enterprise Auth", host, python=python, **expansions) + display_name = get_display_name("Auth Enterprise", host, python=python, **expansions) variant = create_variant( ["test-enterprise-auth"], display_name, host=host, python=python, expansions=expansions ) @@ -467,7 +468,7 @@ def create_pyopenssl_variants(): return variants -def create_storage_engine_tests(): +def create_storage_engine_variants(): host = "rhel8" engines = ["InMemory", "MMAPv1"] variants = [] @@ -490,7 +491,7 @@ def create_storage_engine_tests(): return variants -def create_versioned_api_tests(): +def create_stable_api_variants(): host = "rhel8" tags = ["versionedApi_tag"] tasks = [f".standalone .{v} .noauth .nossl .sync_async" for v in get_versions_from("5.0")] @@ -512,7 +513,7 @@ def create_versioned_api_tests(): # requireApiVersion, and don't automatically add apiVersion to # clients created in the test suite. expansions["ORCHESTRATION_FILE"] = "versioned-api-testing.json" - base_display_name = f"Versioned API {test_type}" + base_display_name = f"Stable API {test_type}" display_name = get_display_name(base_display_name, host, python=python, **expansions) variant = create_variant( tasks, display_name, host=host, python=python, tags=tags, expansions=expansions @@ -528,7 +529,7 @@ def create_green_framework_variants(): host = "rhel8" for python, framework in product([CPYTHONS[0], CPYTHONS[-2]], ["eventlet", "gevent"]): expansions = dict(GREEN_FRAMEWORK=framework, AUTH="auth", SSL="ssl") - display_name = get_display_name(f"{framework.capitalize()}", host, python=python) + display_name = get_display_name(f"Green {framework.capitalize()}", host, python=python) variant = create_variant( tasks, display_name, host=host, python=python, expansions=expansions ) @@ -615,11 +616,15 @@ def create_serverless_variants(): def create_oidc_auth_variants(): variants = [] - for host in ["rhel8", "macos", "win64"]: + other_tasks = ["testazureoidc_task_group", "testgcpoidc_task_group", "testk8soidc_task_group"] + for host in ["ubuntu22", "macos", "win64"]: + tasks = ["testoidc_task_group"] + if host == "ubuntu22": + tasks += other_tasks variants.append( create_variant( - ["testoidc_task_group"], - get_display_name("OIDC Auth", host), + tasks, + get_display_name("Auth OIDC", host), host=host, batchtime=BATCHTIME_WEEK * 2, ) @@ -646,7 +651,7 @@ def create_mockupdb_variants(): return [ create_variant( ["mockupdb"], - get_display_name("MockupDB Tests", host, python=python), + get_display_name("MockupDB", host, python=python), python=python, host=host, ) @@ -700,7 +705,7 @@ def create_aws_auth_variants(): expansions["skip_web_identity_auth_test"] = "true" variant = create_variant( tasks, - get_display_name("AWS Auth", host, python=python), + get_display_name("Auth AWS", host, python=python), host=host, python=python, expansions=expansions, diff --git a/pymongo/auth_oidc_shared.py b/pymongo/auth_oidc_shared.py index 5e3603fa3..9e0acaf6c 100644 --- a/pymongo/auth_oidc_shared.py +++ b/pymongo/auth_oidc_shared.py @@ -116,3 +116,17 @@ class _OIDCGCPCallback(OIDCCallback): def fetch(self, context: OIDCCallbackContext) -> OIDCCallbackResult: resp = _get_gcp_response(self.token_resource, context.timeout_seconds) return OIDCCallbackResult(access_token=resp["access_token"]) + + +class _OIDCK8SCallback(OIDCCallback): + def fetch(self, context: OIDCCallbackContext) -> OIDCCallbackResult: + return OIDCCallbackResult(access_token=_get_k8s_token()) + + +def _get_k8s_token() -> str: + fname = "/var/run/secrets/kubernetes.io/serviceaccount/token" + for key in ["AZURE_FEDERATED_TOKEN_FILE", "AWS_WEB_IDENTITY_TOKEN_FILE"]: + if key in os.environ: + fname = os.environ[key] + with open(fname) as fid: + return fid.read() diff --git a/pymongo/auth_shared.py b/pymongo/auth_shared.py index fa25aa3fa..1e1ce7b4d 100644 --- a/pymongo/auth_shared.py +++ b/pymongo/auth_shared.py @@ -26,6 +26,7 @@ from bson import Binary from pymongo.auth_oidc_shared import ( _OIDCAzureCallback, _OIDCGCPCallback, + _OIDCK8SCallback, _OIDCProperties, _OIDCTestCallback, ) @@ -192,6 +193,9 @@ def _build_credentials_tuple( "GCP provider for MONGODB-OIDC requires a TOKEN_RESOURCE auth mechanism property" ) callback = _OIDCGCPCallback(token_resource) + elif environ == "k8s": + passwd = None + callback = _OIDCK8SCallback() else: raise ConfigurationError(f"unrecognized ENVIRONMENT for MONGODB-OIDC: {environ}") else: diff --git a/requirements/typing.txt b/requirements/typing.txt index db0825c2b..b1f07604d 100644 --- a/requirements/typing.txt +++ b/requirements/typing.txt @@ -1,5 +1,5 @@ mypy==1.13.0 -pyright==1.1.384 +pyright==1.1.385 typing_extensions -r ./encryption.txt -r ./ocsp.txt diff --git a/test/asynchronous/test_auth_spec.py b/test/asynchronous/test_auth_spec.py index a6ab1cb33..e9e43d575 100644 --- a/test/asynchronous/test_auth_spec.py +++ b/test/asynchronous/test_auth_spec.py @@ -25,7 +25,7 @@ from test.asynchronous import AsyncPyMongoTestCase sys.path[0:0] = [""] from test import unittest -from test.unified_format import generate_test_classes +from test.asynchronous.unified_format import generate_test_classes from pymongo import AsyncMongoClient from pymongo.asynchronous.auth_oidc import OIDCCallback diff --git a/test/asynchronous/test_change_stream.py b/test/asynchronous/test_change_stream.py index 98641f46e..8e16fe752 100644 --- a/test/asynchronous/test_change_stream.py +++ b/test/asynchronous/test_change_stream.py @@ -35,7 +35,7 @@ from test.asynchronous import ( async_client_context, unittest, ) -from test.unified_format import generate_test_classes +from test.asynchronous.unified_format import generate_test_classes from test.utils import ( AllowListEventListener, EventListener, diff --git a/test/asynchronous/test_connection_logging.py b/test/asynchronous/test_connection_logging.py index 6bc9835b7..945c6c59b 100644 --- a/test/asynchronous/test_connection_logging.py +++ b/test/asynchronous/test_connection_logging.py @@ -22,7 +22,7 @@ import sys sys.path[0:0] = [""] from test import unittest -from test.unified_format import generate_test_classes +from test.asynchronous.unified_format import generate_test_classes _IS_SYNC = False diff --git a/test/asynchronous/test_crud_unified.py b/test/asynchronous/test_crud_unified.py index 3d8deb36e..e6f42d5bd 100644 --- a/test/asynchronous/test_crud_unified.py +++ b/test/asynchronous/test_crud_unified.py @@ -22,7 +22,7 @@ import sys sys.path[0:0] = [""] from test import unittest -from test.unified_format import generate_test_classes +from test.asynchronous.unified_format import generate_test_classes _IS_SYNC = False diff --git a/test/asynchronous/test_encryption.py b/test/asynchronous/test_encryption.py index e42c85aa7..767b3ecf0 100644 --- a/test/asynchronous/test_encryption.py +++ b/test/asynchronous/test_encryption.py @@ -46,6 +46,7 @@ from test import ( unittest, ) from test.asynchronous.test_bulk import AsyncBulkTestBase +from test.asynchronous.unified_format import generate_test_classes from test.asynchronous.utils_spec_runner import AsyncSpecRunner from test.helpers import ( AWS_CREDS, @@ -56,7 +57,6 @@ from test.helpers import ( KMIP_CREDS, LOCAL_MASTER_KEY, ) -from test.unified_format import generate_test_classes from test.utils import ( AllowListEventListener, OvertCommandListener, diff --git a/test/asynchronous/unified_format.py b/test/asynchronous/unified_format.py index b382db474..f8179dc0c 100644 --- a/test/asynchronous/unified_format.py +++ b/test/asynchronous/unified_format.py @@ -862,7 +862,7 @@ class UnifiedSpecTestMixinV1(AsyncIntegrationTest): return await target.create_data_key(*args, **kwargs) async def _clientEncryptionOperation_getKeys(self, target, *args, **kwargs): - return await (await target.get_keys(*args, **kwargs)).to_list() + return await target.get_keys(*args, **kwargs).to_list() async def _clientEncryptionOperation_deleteKey(self, target, *args, **kwargs): result = await target.delete_key(*args, **kwargs) diff --git a/test/auth/legacy/connection-string.json b/test/auth/legacy/connection-string.json index 67aafbff6..3a099c813 100644 --- a/test/auth/legacy/connection-string.json +++ b/test/auth/legacy/connection-string.json @@ -626,6 +626,26 @@ "uri": "mongodb://user:pass@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:gcp", "valid": false, "credential": null + }, + { + "description": "should recognise the mechanism with k8s provider (MONGODB-OIDC)", + "uri": "mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:k8s", + "valid": true, + "credential": { + "username": null, + "password": null, + "source": "$external", + "mechanism": "MONGODB-OIDC", + "mechanism_properties": { + "ENVIRONMENT": "k8s" + } + } + }, + { + "description": "should throw an error for a username and password with k8s provider (MONGODB-OIDC)", + "uri": "mongodb://user:pass@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:k8s", + "valid": false, + "credential": null } ] } diff --git a/test/auth_oidc/test_auth_oidc.py b/test/auth_oidc/test_auth_oidc.py index 6526391da..a0127304c 100644 --- a/test/auth_oidc/test_auth_oidc.py +++ b/test/auth_oidc/test_auth_oidc.py @@ -37,6 +37,7 @@ from bson import SON from pymongo import MongoClient from pymongo._azure_helpers import _get_azure_response from pymongo._gcp_helpers import _get_gcp_response +from pymongo.auth_oidc_shared import _get_k8s_token from pymongo.cursor_shared import CursorType from pymongo.errors import AutoReconnect, ConfigurationError, OperationFailure from pymongo.hello import HelloCompat @@ -84,6 +85,10 @@ class OIDCTestBase(PyMongoTestCase): opts = parse_uri(self.uri_single)["options"] token_aud = opts["authmechanismproperties"]["TOKEN_RESOURCE"] return _get_gcp_response(token_aud, username)["access_token"] + elif ENVIRON == "k8s": + return _get_k8s_token() + else: + raise ValueError(f"Unknown ENVIRON: {ENVIRON}") @contextmanager def fail_point(self, command_args): @@ -758,7 +763,9 @@ class TestAuthOIDCMachine(OIDCTestBase): kwargs["retryReads"] = False if not len(args): args = [self.uri_single] - return MongoClient(*args, authmechanismproperties=props, **kwargs) + client = MongoClient(*args, authmechanismproperties=props, **kwargs) + self.addCleanup(client.close) + return client def test_1_1_callback_is_called_during_reauthentication(self): # Create a ``MongoClient`` configured with a custom OIDC callback that @@ -768,8 +775,6 @@ class TestAuthOIDCMachine(OIDCTestBase): client.test.test.find_one() # Assert that the callback was called 1 time. self.assertEqual(self.request_called, 1) - # Close the client. - client.close() def test_1_2_callback_is_called_once_for_multiple_connections(self): # Create a ``MongoClient`` configured with a custom OIDC callback that @@ -790,8 +795,6 @@ class TestAuthOIDCMachine(OIDCTestBase): thread.join() # Assert that the callback was called 1 time. self.assertEqual(self.request_called, 1) - # Close the client. - client.close() def test_2_1_valid_callback_inputs(self): # Create a MongoClient configured with an OIDC callback that validates its inputs and returns a valid access token. @@ -800,8 +803,6 @@ class TestAuthOIDCMachine(OIDCTestBase): client.test.test.find_one() # Assert that the OIDC callback was called with the appropriate inputs, including the timeout parameter if possible. Ensure that there are no unexpected fields. self.assertEqual(self.request_called, 1) - # Close the client. - client.close() def test_2_2_oidc_callback_returns_null(self): # Create a MongoClient configured with an OIDC callback that returns null. @@ -813,8 +814,6 @@ class TestAuthOIDCMachine(OIDCTestBase): # Perform a find operation that fails. with self.assertRaises(ValueError): client.test.test.find_one() - # Close the client. - client.close() def test_2_3_oidc_callback_returns_missing_data(self): # Create a MongoClient configured with an OIDC callback that returns data not conforming to the OIDCCredential with missing fields. @@ -829,8 +828,6 @@ class TestAuthOIDCMachine(OIDCTestBase): # Perform a find operation that fails. with self.assertRaises(ValueError): client.test.test.find_one() - # Close the client. - client.close() def test_2_4_invalid_client_configuration_with_callback(self): # Create a MongoClient configured with an OIDC callback and auth mechanism property ENVIRONMENT:test. @@ -870,8 +867,6 @@ class TestAuthOIDCMachine(OIDCTestBase): client.test.test.find_one() # Verify that the callback was called 1 time. self.assertEqual(self.request_called, 1) - # Close the client. - client.close() def test_3_2_authentication_failures_without_cached_tokens_returns_an_error(self): # Create a MongoClient configured with retryReads=false and an OIDC callback that always returns invalid access tokens. @@ -889,8 +884,6 @@ class TestAuthOIDCMachine(OIDCTestBase): client.test.test.find_one() # Verify that the callback was called 1 time. self.assertEqual(callback.count, 1) - # Close the client. - client.close() def test_3_3_unexpected_error_code_does_not_clear_cache(self): # Create a ``MongoClient`` with a human callback that returns a valid token @@ -916,9 +909,6 @@ class TestAuthOIDCMachine(OIDCTestBase): # Assert that the callback has been called once. self.assertEqual(self.request_called, 1) - # Close the client. - client.close() - def test_4_1_reauthentication_succeds(self): # Create a ``MongoClient`` configured with a custom OIDC callback that # implements the provider logic. @@ -938,9 +928,6 @@ class TestAuthOIDCMachine(OIDCTestBase): # handshake, and again during reauthentication). self.assertEqual(self.request_called, 2) - # Close the client. - client.close() - def test_4_2_read_commands_fail_if_reauthentication_fails(self): # Create a ``MongoClient`` whose OIDC callback returns one good token and then # bad tokens after the first call. @@ -977,9 +964,6 @@ class TestAuthOIDCMachine(OIDCTestBase): # Verify that the callback was called 2 times. self.assertEqual(callback.count, 2) - # Close the client. - client.close() - def test_4_3_write_commands_fail_if_reauthentication_fails(self): # Create a ``MongoClient`` whose OIDC callback returns one good token and then # bad token after the first call. @@ -1016,12 +1000,9 @@ class TestAuthOIDCMachine(OIDCTestBase): # Verify that the callback was called 2 times. self.assertEqual(callback.count, 2) - # Close the client. - client.close() - def test_4_4_speculative_authentication_should_be_ignored_on_reauthentication(self): # Create an OIDC configured client that can listen for `SaslStart` commands. - listener = OvertCommandListener() + listener = EventListener() client = self.create_client(event_listeners=[listener]) # Preload the *Client Cache* with a valid access token to enforce Speculative Authentication. @@ -1061,9 +1042,6 @@ class TestAuthOIDCMachine(OIDCTestBase): # Assert there were `SaslStart` commands executed. assert any(event.command_name.lower() == "saslstart" for event in listener.started_events) - # Close the client. - client.close() - def test_5_1_azure_with_no_username(self): if ENVIRON != "azure": raise unittest.SkipTest("Test is only supported on Azure") @@ -1073,7 +1051,6 @@ class TestAuthOIDCMachine(OIDCTestBase): props = dict(TOKEN_RESOURCE=resource, ENVIRONMENT="azure") client = self.create_client(authMechanismProperties=props) client.test.test.find_one() - client.close() def test_5_2_azure_with_bad_username(self): if ENVIRON != "azure": @@ -1086,7 +1063,6 @@ class TestAuthOIDCMachine(OIDCTestBase): client = self.create_client(username="bad", authmechanismproperties=props) with self.assertRaises(ValueError): client.test.test.find_one() - client.close() def test_speculative_auth_success(self): client1 = self.create_client() @@ -1108,10 +1084,6 @@ class TestAuthOIDCMachine(OIDCTestBase): # Perform a find operation. client2.test.test.find_one() - # Close the clients. - client2.close() - client1.close() - def test_reauthentication_succeeds_multiple_connections(self): client1 = self.create_client() client2 = self.create_client() @@ -1151,8 +1123,6 @@ class TestAuthOIDCMachine(OIDCTestBase): client2.test.test.find_one() self.assertEqual(self.request_called, 3) - client1.close() - client2.close() if __name__ == "__main__": diff --git a/test/unified_format.py b/test/unified_format.py index 0da616830..80c37470e 100644 --- a/test/unified_format.py +++ b/test/unified_format.py @@ -858,7 +858,7 @@ class UnifiedSpecTestMixinV1(IntegrationTest): return target.create_data_key(*args, **kwargs) def _clientEncryptionOperation_getKeys(self, target, *args, **kwargs): - return (target.get_keys(*args, **kwargs)).to_list() + return target.get_keys(*args, **kwargs).to_list() def _clientEncryptionOperation_deleteKey(self, target, *args, **kwargs): result = target.delete_key(*args, **kwargs) diff --git a/test/unified_format_shared.py b/test/unified_format_shared.py index f315a77f4..1c87fb3f1 100644 --- a/test/unified_format_shared.py +++ b/test/unified_format_shared.py @@ -137,6 +137,8 @@ elif OIDC_ENV == "gcp": "ENVIRONMENT": "gcp", "TOKEN_RESOURCE": os.environ["GCPOIDC_AUDIENCE"], } +elif OIDC_ENV == "k8s": + PLACEHOLDER_MAP["/uriOptions/authMechanismProperties"] = {"ENVIRONMENT": "k8s"} def with_metaclass(meta, *bases):