From f6f7d3cf8f037a28b864fdfb329ffe98aaf48077 Mon Sep 17 00:00:00 2001 From: ekovalets Date: Mon, 27 Oct 2025 12:18:32 -0700 Subject: [PATCH] SERVER-112109: Evergreen Task and scripts to run Server SBOM upload to Google Drive at release (#42893) GitOrigin-RevId: 808122c5304ee055149964ad08ab64b79c4e2f1f --- .github/CODEOWNERS | 3 + .../tasks/release_tasks.yml | 78 +++++++ .../variants/misc/misc.yml | 1 + .../variants/release/release.yml | 1 + .../security_reporting_scripts/BUILD.bazel | 17 ++ .../security_reporting_scripts/OWNERS.yml | 5 + .../augment_sbom.sh | 55 +++++ .../upload_to_google_drive.py | 119 +++++++++++ .../write_aws_creds_to_silkbomb_env_file.sh | 21 ++ poetry.lock | 201 +++++++++++++++++- pyproject.toml | 2 + 11 files changed, 498 insertions(+), 5 deletions(-) create mode 100644 evergreen/functions/security_reporting_scripts/BUILD.bazel create mode 100644 evergreen/functions/security_reporting_scripts/OWNERS.yml create mode 100644 evergreen/functions/security_reporting_scripts/augment_sbom.sh create mode 100644 evergreen/functions/security_reporting_scripts/upload_to_google_drive.py create mode 100644 evergreen/functions/security_reporting_scripts/write_aws_creds_to_silkbomb_env_file.sh diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 69712a6e897..afab0fcf70a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -373,6 +373,9 @@ WORKSPACE.bazel @10gen/devprod-build @svc-auto-approve-bot /evergreen/generate_sast_report.sh @10gen/devprod-release-infrastructure @svc-auto-approve-bot /evergreen/write_sast_report_env_file.sh @10gen/devprod-release-infrastructure @svc-auto-approve-bot +# The following patterns are parsed from ./evergreen/functions/security_reporting_scripts/OWNERS.yml +/evergreen/functions/security_reporting_scripts/ @10gen/platsec-server @svc-auto-approve-bot + # The following patterns are parsed from ./jstests/OWNERS.yml /jstests/README.md @10gen/devprod-correctness @svc-auto-approve-bot /jstests/tags.md @10gen/devprod-correctness @svc-auto-approve-bot diff --git a/etc/evergreen_yml_components/tasks/release_tasks.yml b/etc/evergreen_yml_components/tasks/release_tasks.yml index 8af9427e924..385a49fd34b 100644 --- a/etc/evergreen_yml_components/tasks/release_tasks.yml +++ b/etc/evergreen_yml_components/tasks/release_tasks.yml @@ -55,3 +55,81 @@ tasks: remote_file: ${project}/${build_variant}/${revision}/artifacts/${build_id}/${task_name}/ permissions: private visibility: signed + + - name: publish-augmented-sbom + tags: ["auxiliary", "assigned_to_jira_team_platsec_server"] + depends_on: + - name: version_expansions_gen + variant: generate-tasks-for-version + exec_timeout_secs: 600 # 10 minute timeout + commands: + - command: manifest.load + - func: "git get project and add git tag" + - func: "get version expansions" + - func: "apply version expansions" + - func: "f_expansions_write" + - func: "kill processes" + - func: "cleanup environment" + - func: "set up venv" + - func: "upload pip requirements" + - command: ec2.assume_role + display_name: Assume Silkbomb IAM role + params: + role_arn: arn:aws:iam::119629040606:role/silkbomb + - func: "f_expansions_write" + - command: subprocess.exec + display_name: Write temporary AWS credentials to Silkbomb environment file + params: + binary: bash + args: + - "src/evergreen/functions/security_reporting_scripts/write_aws_creds_to_silkbomb_env_file.sh" + include_expansions_in_env: + [AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN] + - command: ec2.assume_role + display_name: Assume DevProd Platforms ECR readonly IAM role + params: + role_arn: arn:aws:iam::901841024863:role/ecr-role-evergreen-ro + - func: "f_expansions_write" + - command: subprocess.exec + display_name: Run Silkbomb to augment SBOM with VEX data + params: + binary: bash + args: + - "src/evergreen/functions/security_reporting_scripts/augment_sbom.sh" + include_expansions_in_env: + [AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN] + env: + REQUESTER: ${requester} + BRANCH_NAME: ${branch_name} + GITHUB_ORG: ${github_org} + GITHUB_REPO: ${github_repo} + CONTAINER_COMMAND: docker # podman or docker + CONTAINER_OPTIONS: --pull=always --platform=linux/amd64 -i --rm + CONTAINER_ENV_FILES: ${workdir}/silkbomb.env + CONTAINER_VOLUMES: -v ${workdir}:/workdir + CONTAINER_IMAGE: 901841024863.dkr.ecr.us-east-1.amazonaws.com/release-infrastructure/silkbomb:2.0 + SBOM_REPO_PATH: sbom.json + SBOM_OUT_PATH: ${workdir}/sbom-with-vex-${branch_name}.json + SILKBOMB_COMMAND: augment + SILKBOMB_ARGS: --sbom-in /workdir/src/sbom.json --sbom-out /workdir/src/sbom-with-vex-${branch_name}.json --repo ${github_repo} --branch ${branch_name} --project tarun_test + - command: subprocess.exec + display_name: Upload SBOM to Google Drive" + params: + binary: bash + args: + - "${workdir}/src/evergreen/run_python_script.sh" + - "${workdir}/src/evergreen/functions/security_reporting_scripts/upload_to_google_drive.py" + - "${workdir}/src/sbom-with-vex-${branch_name}.json" + env: + WORK_DIR: ${workdir} + GITHUB_COMMIT: ${github_commit} + TRIGGERED_BY_GIT_TAG: ${triggered_by_git_tag} + MONGODB_VERSION: ${version} + MONGODB_RELEASE_BRANCH: ${branch_name} + SBOM_OUT_PATH: ${workdir}/sbom-with-vex-${branch_name}.json + UPLOAD_FILE_NAME: "[${version}] MongoDB Server Enterprise SBOM" + SBOM_REPORT_TEST_GOOGLE_DRIVE_FOLDER_ID: ${SBOM_REPORT_TEST_GOOGLE_DRIVE_FOLDER_ID} + SBOM_REPORT_RELEASES_GOOGLE_DRIVE_FOLDER_ID: ${SBOM_REPORT_RELEASES_GOOGLE_DRIVE_FOLDER_ID} + SAST_REPORT_UPLOAD_GOOGLE_CLIENT_ID: ${SAST_REPORT_UPLOAD_GOOGLE_CLIENT_ID} + SAST_REPORT_UPLOAD_GOOGLE_CLIENT_REFRESH_TOKEN: ${SAST_REPORT_UPLOAD_GOOGLE_CLIENT_REFRESH_TOKEN} + SAST_REPORT_UPLOAD_GOOGLE_CLIENT_SECRET: ${SAST_REPORT_UPLOAD_GOOGLE_CLIENT_SECRET} diff --git a/etc/evergreen_yml_components/variants/misc/misc.yml b/etc/evergreen_yml_components/variants/misc/misc.yml index bfccea41ace..a5dd9df78f7 100644 --- a/etc/evergreen_yml_components/variants/misc/misc.yml +++ b/etc/evergreen_yml_components/variants/misc/misc.yml @@ -52,6 +52,7 @@ buildvariants: - devprod_coverity tasks: - name: publish-sast-report + - name: publish-augmented-sbom - name: promote-custom-build display_name: "Promote Custom Build" diff --git a/etc/evergreen_yml_components/variants/release/release.yml b/etc/evergreen_yml_components/variants/release/release.yml index e20b0b6b599..5e306c06cd0 100644 --- a/etc/evergreen_yml_components/variants/release/release.yml +++ b/etc/evergreen_yml_components/variants/release/release.yml @@ -8,3 +8,4 @@ buildvariants: - devprod_coverity tasks: - name: publish-sast-report + - name: publish-augmented-sbom diff --git a/evergreen/functions/security_reporting_scripts/BUILD.bazel b/evergreen/functions/security_reporting_scripts/BUILD.bazel new file mode 100644 index 00000000000..9ca1bc981ff --- /dev/null +++ b/evergreen/functions/security_reporting_scripts/BUILD.bazel @@ -0,0 +1,17 @@ +package(default_visibility = ["//visibility:public"]) + +sh_binary( + name = "augment_sbom", + srcs = ["augment_sbom.sh"], +) + +sh_binary( + name = "write_aws_creds_to_silkbomb_env_file", + srcs = ["write_aws_creds_to_silkbomb_env_file.sh"], +) + +py_library( + name = "all_python_files", + srcs = glob(["*.py"]), + visibility = ["//visibility:public"], +) diff --git a/evergreen/functions/security_reporting_scripts/OWNERS.yml b/evergreen/functions/security_reporting_scripts/OWNERS.yml new file mode 100644 index 00000000000..14613f35dfc --- /dev/null +++ b/evergreen/functions/security_reporting_scripts/OWNERS.yml @@ -0,0 +1,5 @@ +version: 2.0.0 +filters: + - "*": + approvers: + - 10gen/platsec-server diff --git a/evergreen/functions/security_reporting_scripts/augment_sbom.sh b/evergreen/functions/security_reporting_scripts/augment_sbom.sh new file mode 100644 index 00000000000..b25e39c873e --- /dev/null +++ b/evergreen/functions/security_reporting_scripts/augment_sbom.sh @@ -0,0 +1,55 @@ +# !/bin/bash +# Augment SBOM using SilkBomb inside a container. +# +# Usage: +# augment_sbom +# +# The script uses SilkBomb. +# See: https://docs.devprod.prod.corp.mongodb.com/mms/python/src/sbom/silkbomb/ +# +# Required system environment variables: +# AWS_ACCESS_KEY_ID +# AWS_SECRET_ACCESS_KEY +# AWS_SESSION_TOKEN +# +# Required script env variables: +# CONTAINER_COMMAND +# CONTAINER_OPTIONS +# CONTAINER_ENV_FILES +# CONTAINER_VOLUMES +# CONTAINER_IMAGE +# SBOM_REPO_PATH +# SBOM_OUT_PATH +# SILKBOMB_COMMAND +# SILKBOMB_ARGS +# requester +# branch_name +# github_org +# github_repo +# workdir + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" +. "$DIR/../../prelude.sh" + +set -o errexit +set -o verbose +set -o pipefail + +read -ra OPTS_ARRAY <<<"$CONTAINER_OPTIONS" +read -ra VOLUMES_ARRAY <<<"$CONTAINER_VOLUMES" +read -ra ARGS_ARRAY <<<"$SILKBOMB_ARGS" + +echo "--> Logging in to AWS ECR..." +aws ecr get-login-password --region us-east-1 | "${CONTAINER_COMMAND}" login --username AWS --password-stdin 901841024863.dkr.ecr.us-east-1.amazonaws.com + +echo "--> Running the container..." +# The "${VAR[@]}" syntax expands arrays safely, with each element becoming a distinct argument. +"${CONTAINER_COMMAND}" run \ + "${OPTS_ARRAY[@]}" \ + --env-file "${CONTAINER_ENV_FILES}" \ + "${VOLUMES_ARRAY[@]}" \ + "${CONTAINER_IMAGE}" \ + "${SILKBOMB_COMMAND}" \ + "${ARGS_ARRAY[@]}" + +echo "--> Script finished successfully." diff --git a/evergreen/functions/security_reporting_scripts/upload_to_google_drive.py b/evergreen/functions/security_reporting_scripts/upload_to_google_drive.py new file mode 100644 index 00000000000..b0967284039 --- /dev/null +++ b/evergreen/functions/security_reporting_scripts/upload_to_google_drive.py @@ -0,0 +1,119 @@ +import os +import sys +from pathlib import Path + +import typer +from google.oauth2.credentials import Credentials +from googleapiclient.discovery import build +from googleapiclient.errors import HttpError +from googleapiclient.http import MediaFileUpload + +app = typer.Typer(add_completion=False) + + +@app.command() +def upload( + input_file: Path = typer.Argument( + ..., + exists=True, + file_okay=True, + dir_okay=False, + readable=True, + resolve_path=True, + help="The path to the file to upload.", + ), + client_id: str = typer.Option( + ..., + envvar="SAST_REPORT_UPLOAD_GOOGLE_CLIENT_ID", + help="The OAuth2 client ID for Google API.", + ), + client_secret: str = typer.Option( + ..., + envvar="SAST_REPORT_UPLOAD_GOOGLE_CLIENT_SECRET", + help="The OAuth2 client secret for Google API.", + ), + refresh_token: str = typer.Option( + ..., + envvar="SAST_REPORT_UPLOAD_GOOGLE_CLIENT_REFRESH_TOKEN", + help="The OAuth2 refresh token for Google API.", + ), + branch: str = typer.Option( + ..., envvar="MONGODB_RELEASE_BRANCH", help="The MongoDB release branch." + ), + test_folder_id: str = typer.Option( + ..., + envvar="SBOM_REPORT_TEST_GOOGLE_DRIVE_FOLDER_ID", + help="The ID of the Google Drive folder for test uploads.", + ), + releases_folder_id: str = typer.Option( + ..., + envvar="SBOM_REPORT_RELEASES_GOOGLE_DRIVE_FOLDER_ID", + help="The ID of the Google Drive folder for releases.", + ), + triggered_by_tag: str = typer.Option( + "", + envvar="TRIGGERED_BY_GIT_TAG", + help="Indicates if the upload was triggered by a git tag.", + ), + version: str = typer.Option( + "", envvar="MONGODB_VERSION", help="The version of MongoDB being processed." + ), + upload_file_name: str = typer.Option( + None, + envvar="UPLOAD_FILE_NAME", + help="Optional upload file to use. If not provided, the input file name will be used.", + ), +): + print("Starting file upload process to Google Drive.") + + try: + creds_info = { + "client_id": client_id, + "client_secret": client_secret, + "refresh_token": refresh_token, + "token_uri": "https://oauth2.googleapis.com/token", + } + creds = Credentials.from_authorized_user_info( + info=creds_info, scopes=["https://www.googleapis.com/auth/drive"] + ) + drive_service = build("drive", "v3", credentials=creds) + print("Authenticated with Google Drive API successfully.") + except Exception as e: + print(f"Failed to authenticate with Google API: {e}") + sys.exit(1) + + folder_id = releases_folder_id if triggered_by_tag.lower() == "true" else test_folder_id + + if upload_file_name is None: + input_file_name_str = str(input_file.resolve().name) + else: + _, file_extension = os.path.splitext(input_file.resolve().name) + input_file_name_str = f"{upload_file_name}{file_extension}" + + file_metadata = {"name": input_file_name_str, "parents": [folder_id]} + media = MediaFileUpload(str(input_file), mimetype="text/html", resumable=True) + + try: + print(f"Uploading '{input_file}' to Google Drive...") + print(f"File name on Drive: '{input_file_name_str}'") + file = ( + drive_service.files() + .create( + body=file_metadata, + media_body=media, + fields="id, webViewLink", + supportsAllDrives=True, + ) + .execute() + ) + print("Upload complete.") + print(f"File ID: {file.get('id')}") + print(f"View Link: {file.get('webViewLink')}") + + except HttpError as error: + print(f"An API error occurred: {error}") + sys.exit(1) + + +if __name__ == "__main__": + app() diff --git a/evergreen/functions/security_reporting_scripts/write_aws_creds_to_silkbomb_env_file.sh b/evergreen/functions/security_reporting_scripts/write_aws_creds_to_silkbomb_env_file.sh new file mode 100644 index 00000000000..41c0bb42e71 --- /dev/null +++ b/evergreen/functions/security_reporting_scripts/write_aws_creds_to_silkbomb_env_file.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# +# This is an auxiliary script that writes AWS credentials to an env file. +# Being used by augment_sbom.sh script and SBOM upload tasks to prepare the env file for SilkBomb. +# +# Usage: +# write_aws_creds_to_silkbomb_env_file.sh +# +# Required system environment variables: +# AWS_ACCESS_KEY_ID +# AWS_SECRET_ACCESS_KEY +# AWS_SESSION_TOKEN + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" +. "$DIR/../../prelude.sh" + +cat <"${workdir}/silkbomb.env" +AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} +AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} +AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN} +EOF diff --git a/poetry.lock b/poetry.lock index d7ad2c3df1b..548b0f910d5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -220,6 +220,19 @@ dev = ["CacheControl[filecache,redis]", "build", "cherrypy", "codespell[tomli]", filecache = ["filelock (>=3.8.0)"] redis = ["redis (>=2.10.5)"] +[[package]] +name = "cachetools" +version = "6.2.1" +description = "Extensible memoizing collections and decorators" +optional = false +python-versions = ">=3.9" +groups = ["testing"] +markers = "platform_machine != \"s390x\" and platform_machine != \"ppc64le\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\"" +files = [ + {file = "cachetools-6.2.1-py3-none-any.whl", hash = "sha256:09868944b6dde876dfd44e1d47e18484541eaf12f26f29b7af91b26cc892d701"}, + {file = "cachetools-6.2.1.tar.gz", hash = "sha256:3f391e4bd8f8bf0931169baf7456cc822705f4e2a31f840d218f445b9a854201"}, +] + [[package]] name = "certifi" version = "2025.1.31" @@ -1224,6 +1237,120 @@ gitdb = ">=4.0.1,<5" doc = ["sphinx (>=7.1.2,<7.2)", "sphinx-autodoc-typehints", "sphinx_rtd_theme"] test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions"] +[[package]] +name = "google-api-core" +version = "2.26.0" +description = "Google API client core library" +optional = false +python-versions = ">=3.7" +groups = ["testing"] +markers = "platform_machine != \"s390x\" and platform_machine != \"ppc64le\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\"" +files = [ + {file = "google_api_core-2.26.0-py3-none-any.whl", hash = "sha256:2b204bd0da2c81f918e3582c48458e24c11771f987f6258e6e227212af78f3ed"}, + {file = "google_api_core-2.26.0.tar.gz", hash = "sha256:e6e6d78bd6cf757f4aee41dcc85b07f485fbb069d5daa3afb126defba1e91a62"}, +] + +[package.dependencies] +google-auth = ">=2.14.1,<3.0.0" +googleapis-common-protos = ">=1.56.2,<2.0.0" +proto-plus = [ + {version = ">=1.25.0,<2.0.0", markers = "python_version >= \"3.13\""}, + {version = ">=1.22.3,<2.0.0", markers = "python_version < \"3.13\""}, +] +protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<7.0.0" +requests = ">=2.18.0,<3.0.0" + +[package.extras] +async-rest = ["google-auth[aiohttp] (>=2.35.0,<3.0.0)"] +grpc = ["grpcio (>=1.33.2,<2.0.0)", "grpcio (>=1.49.1,<2.0.0)", "grpcio (>=1.75.1,<2.0.0)", "grpcio-status (>=1.33.2,<2.0.0)", "grpcio-status (>=1.49.1,<2.0.0)", "grpcio-status (>=1.75.1,<2.0.0)"] +grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.0)"] +grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.0)"] + +[[package]] +name = "google-api-python-client" +version = "2.185.0" +description = "Google API Client Library for Python" +optional = false +python-versions = ">=3.7" +groups = ["testing"] +markers = "platform_machine != \"s390x\" and platform_machine != \"ppc64le\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\"" +files = [ + {file = "google_api_python_client-2.185.0-py3-none-any.whl", hash = "sha256:00fe173a4b346d2397fbe0d37ac15368170dfbed91a0395a66ef2558e22b93fc"}, + {file = "google_api_python_client-2.185.0.tar.gz", hash = "sha256:aa1b338e4bb0f141c2df26743f6b46b11f38705aacd775b61971cbc51da089c3"}, +] + +[package.dependencies] +google-api-core = ">=1.31.5,<2.0.dev0 || >2.3.0,<3.0.0" +google-auth = ">=1.32.0,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0" +google-auth-httplib2 = ">=0.2.0,<1.0.0" +httplib2 = ">=0.19.0,<1.0.0" +uritemplate = ">=3.0.1,<5" + +[[package]] +name = "google-auth" +version = "2.41.1" +description = "Google Authentication Library" +optional = false +python-versions = ">=3.7" +groups = ["testing"] +markers = "platform_machine != \"s390x\" and platform_machine != \"ppc64le\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\"" +files = [ + {file = "google_auth-2.41.1-py2.py3-none-any.whl", hash = "sha256:754843be95575b9a19c604a848a41be03f7f2afd8c019f716dc1f51ee41c639d"}, + {file = "google_auth-2.41.1.tar.gz", hash = "sha256:b76b7b1f9e61f0cb7e88870d14f6a94aeef248959ef6992670efee37709cbfd2"}, +] + +[package.dependencies] +cachetools = ">=2.0.0,<7.0" +pyasn1-modules = ">=0.2.1" +rsa = ">=3.1.4,<5" + +[package.extras] +aiohttp = ["aiohttp (>=3.6.2,<4.0.0)", "requests (>=2.20.0,<3.0.0)"] +enterprise-cert = ["cryptography", "pyopenssl"] +pyjwt = ["cryptography (<39.0.0)", "cryptography (>=38.0.3)", "pyjwt (>=2.0)"] +pyopenssl = ["cryptography (<39.0.0)", "cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] +reauth = ["pyu2f (>=0.1.5)"] +requests = ["requests (>=2.20.0,<3.0.0)"] +testing = ["aiohttp (<3.10.0)", "aiohttp (>=3.6.2,<4.0.0)", "aioresponses", "cryptography (<39.0.0)", "cryptography (<39.0.0)", "cryptography (>=38.0.3)", "cryptography (>=38.0.3)", "flask", "freezegun", "grpcio", "mock", "oauth2client", "packaging", "pyjwt (>=2.0)", "pyopenssl (<24.3.0)", "pyopenssl (>=20.0.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-localserver", "pyu2f (>=0.1.5)", "requests (>=2.20.0,<3.0.0)", "responses", "urllib3"] +urllib3 = ["packaging", "urllib3"] + +[[package]] +name = "google-auth-httplib2" +version = "0.2.0" +description = "Google Authentication Library: httplib2 transport" +optional = false +python-versions = "*" +groups = ["testing"] +markers = "platform_machine != \"s390x\" and platform_machine != \"ppc64le\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\"" +files = [ + {file = "google-auth-httplib2-0.2.0.tar.gz", hash = "sha256:38aa7badf48f974f1eb9861794e9c0cb2a0511a4ec0679b1f886d108f5640e05"}, + {file = "google_auth_httplib2-0.2.0-py2.py3-none-any.whl", hash = "sha256:b65a0a2123300dd71281a7bf6e64d65a0759287df52729bdd1ae2e47dc311a3d"}, +] + +[package.dependencies] +google-auth = "*" +httplib2 = ">=0.19.0" + +[[package]] +name = "google-auth-oauthlib" +version = "1.2.2" +description = "Google Authentication Library" +optional = false +python-versions = ">=3.6" +groups = ["testing"] +markers = "platform_machine != \"s390x\" and platform_machine != \"ppc64le\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\"" +files = [ + {file = "google_auth_oauthlib-1.2.2-py3-none-any.whl", hash = "sha256:fd619506f4b3908b5df17b65f39ca8d66ea56986e5472eb5978fd8f3786f00a2"}, + {file = "google_auth_oauthlib-1.2.2.tar.gz", hash = "sha256:11046fb8d3348b296302dd939ace8af0a724042e8029c1b872d87fabc9f41684"}, +] + +[package.dependencies] +google-auth = ">=2.15.0" +requests-oauthlib = ">=0.7.0" + +[package.extras] +tool = ["click (>=6.0.0)"] + [[package]] name = "googleapis-common-protos" version = "1.66.0" @@ -1409,6 +1536,22 @@ files = [ {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, ] +[[package]] +name = "httplib2" +version = "0.22.0" +description = "A comprehensive HTTP client library." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["testing"] +markers = "platform_machine != \"s390x\" and platform_machine != \"ppc64le\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\"" +files = [ + {file = "httplib2-0.22.0-py3-none-any.whl", hash = "sha256:14ae0a53c1ba8f3d37e9e27cf37eabb0fb9980f435ba405d546948b009dd64dc"}, + {file = "httplib2-0.22.0.tar.gz", hash = "sha256:d7a10bc5ef5ab08322488bde8c726eeee5c8618723fdb399597ec58f3d82df81"}, +] + +[package.dependencies] +pyparsing = {version = ">=2.4.2,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.0.2 || >3.0.2,<3.0.3 || >3.0.3,<4", markers = "python_version > \"3.0\""} + [[package]] name = "hyperlink" version = "21.0.0" @@ -2498,8 +2641,8 @@ files = [ [package.dependencies] googleapis-common-protos = ">=1.57,<2.0" grpcio = [ - {version = ">=1.63.2,<2.0.0", markers = "python_version < \"3.13\""}, {version = ">=1.66.2,<2.0.0", markers = "python_version >= \"3.13\""}, + {version = ">=1.63.2,<2.0.0", markers = "python_version < \"3.13\""}, ] opentelemetry-api = ">=1.15,<2.0" opentelemetry-exporter-otlp-proto-common = "1.35.0" @@ -2771,6 +2914,25 @@ python-utils = ">=3.8.1" docs = ["sphinx (>=1.8.5)", "sphinx-autodoc-typehints (>=1.6.0)"] tests = ["dill (>=0.3.6)", "flake8 (>=3.7.7)", "freezegun (>=0.3.11)", "pytest (>=4.6.9)", "pytest-cov (>=2.6.1)", "pytest-mypy", "pywin32", "sphinx (>=1.8.5)"] +[[package]] +name = "proto-plus" +version = "1.26.1" +description = "Beautiful, Pythonic protocol buffers" +optional = false +python-versions = ">=3.7" +groups = ["testing"] +markers = "platform_machine != \"s390x\" and platform_machine != \"ppc64le\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\"" +files = [ + {file = "proto_plus-1.26.1-py3-none-any.whl", hash = "sha256:13285478c2dcf2abb829db158e1047e2f1e8d63a077d94263c2b88b043c75a66"}, + {file = "proto_plus-1.26.1.tar.gz", hash = "sha256:21a515a4c4c0088a773899e23c7bbade3d18f9c66c73edd4c7ee3816bc96a012"}, +] + +[package.dependencies] +protobuf = ">=3.19.0,<7.0.0" + +[package.extras] +testing = ["google-api-core (>=1.31.5)"] + [[package]] name = "protobuf" version = "5.29.3" @@ -2878,7 +3040,7 @@ version = "0.6.1" description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" optional = false python-versions = ">=3.8" -groups = ["external-auth"] +groups = ["external-auth", "testing"] markers = "platform_machine != \"s390x\" and platform_machine != \"ppc64le\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\"" files = [ {file = "pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629"}, @@ -2891,7 +3053,7 @@ version = "0.4.1" description = "A collection of ASN.1-based protocols modules" optional = false python-versions = ">=3.8" -groups = ["external-auth"] +groups = ["external-auth", "testing"] markers = "platform_machine != \"s390x\" and platform_machine != \"ppc64le\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\"" files = [ {file = "pyasn1_modules-0.4.1-py3-none-any.whl", hash = "sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd"}, @@ -3210,7 +3372,7 @@ version = "2.4.7" description = "Python parsing module" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -groups = ["external-auth"] +groups = ["external-auth", "testing"] markers = "platform_machine != \"s390x\" and platform_machine != \"ppc64le\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\"" files = [ {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, @@ -4003,6 +4165,22 @@ files = [ {file = "rpds_py-0.22.3.tar.gz", hash = "sha256:e32fee8ab45d3c2db6da19a5323bc3362237c8b653c70194414b892fd06a080d"}, ] +[[package]] +name = "rsa" +version = "4.9.1" +description = "Pure-Python RSA implementation" +optional = false +python-versions = "<4,>=3.6" +groups = ["testing"] +markers = "platform_machine != \"s390x\" and platform_machine != \"ppc64le\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\"" +files = [ + {file = "rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762"}, + {file = "rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75"}, +] + +[package.dependencies] +pyasn1 = ">=0.1.3" + [[package]] name = "ruff" version = "0.6.9" @@ -5152,6 +5330,19 @@ files = [ {file = "unittest_xml_reporting-3.0.4-py2.py3-none-any.whl", hash = "sha256:7bf515ea8cb244255a25100cd29db611a73f8d3d0aaf672ed3266307e14cc1ca"}, ] +[[package]] +name = "uritemplate" +version = "4.2.0" +description = "Implementation of RFC 6570 URI Templates" +optional = false +python-versions = ">=3.9" +groups = ["testing"] +markers = "platform_machine != \"s390x\" and platform_machine != \"ppc64le\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\"" +files = [ + {file = "uritemplate-4.2.0-py3-none-any.whl", hash = "sha256:962201ba1c4edcab02e60f9a0d3821e82dfc5d2d6662a21abd533879bdb8a686"}, + {file = "uritemplate-4.2.0.tar.gz", hash = "sha256:480c2ed180878955863323eea31b0ede668795de182617fef9c6ca09e6ec9d0e"}, +] + [[package]] name = "urllib3" version = "2.3.0" @@ -5580,4 +5771,4 @@ libdeps = ["cxxfilt", "eventlet", "flask", "flask-cors", "gevent", "lxml", "prog [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0" -content-hash = "5777da1d1d7bbffd38a9545aa3e3949ba45e603ee6fd1545a165c6b252fb5661" +content-hash = "c433563364aaf4a17f7f866bc7f48d28b7a3a318b05a6ecf569f3811a201e8f4" diff --git a/pyproject.toml b/pyproject.toml index 0f6b7ae7050..61280524ce8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -175,6 +175,8 @@ geckodriver-autoinstaller = "^0.1.0" retry = "^0.9.2" gdbmongo = "^0.16.0" googleapis-common-protos = "^1.63.2" +google-api-python-client="^2.19.0" +google-auth-oauthlib="^1.2.1" gcovr = "7.2" opentelemetry-api = "*" opentelemetry-sdk = "*"