From 26a4fe03bb3eb9adb7ff2ea45ab08d40e6a496ba Mon Sep 17 00:00:00 2001 From: tsgoff Date: Wed, 14 Jan 2026 18:25:11 +0100 Subject: [PATCH] feat(backup): S3 target supports optional endpoint_url (e.g. for Backblaze B2) The S3 backup target can now be used with any S3-compatible endpoint by optionally providing an endpoint_url parameter. This enables usage with services like Backblaze B2 Cloud Storage. --- cmk/utils/backup/targets/aws_s3_bucket.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/cmk/utils/backup/targets/aws_s3_bucket.py b/cmk/utils/backup/targets/aws_s3_bucket.py index 61426ccba07..a8f5f9926a3 100644 --- a/cmk/utils/backup/targets/aws_s3_bucket.py +++ b/cmk/utils/backup/targets/aws_s3_bucket.py @@ -14,10 +14,11 @@ from cmk.utils.password_store import extract, PasswordId -class S3Params(TypedDict): +class S3Params(TypedDict, total=False): access_key: str secret: PasswordId bucket: str + endpoint_url: str # Optional: für S3-kompatible Anbieter wie Backblaze class S3Bucket: @@ -27,16 +28,17 @@ def __init__(self, params: S3Params) -> None: if not (secret_extracted := extract(params["secret"])): raise MKGeneralException("Failed to retrieve secret") - self.client: Final = boto3.client( - "s3", + + endpoint_url = params.get("endpoint_url") + client_args = dict( aws_access_key_id=params["access_key"], aws_secret_access_key=secret_extracted, ) - self.bucket: Final = boto3.resource( - "s3", - aws_access_key_id=params["access_key"], - aws_secret_access_key=secret_extracted, - ).Bucket(params["bucket"]) + if endpoint_url: + client_args["endpoint_url"] = endpoint_url + + self.client: Final = boto3.client("s3", **client_args) + self.bucket: Final = boto3.resource("s3", **client_args).Bucket(params["bucket"]) def ready(self) -> None: try: