diff --git a/docs/user-guide/gcs.rst b/docs/user-guide/gcs.rst index 906bca03..35be9e96 100644 --- a/docs/user-guide/gcs.rst +++ b/docs/user-guide/gcs.rst @@ -27,13 +27,16 @@ Then, do the following: from safir.gcs import SignedURLService - url_service = SignedURLService(timedelta(hours=1), "service-account") + url_service = SignedURLService("service-account") url = url_service.signed_url("s3://bucket/path/to/file", "application/fits") -The first parameter to the constructor is the lifetime of signed URLs, and the second is the name of the Google Cloud service account that will be used to sign the URLs. +The argument to the constructor is the name of the Google Cloud service account that will be used to sign the URLs. This should be the one for which the workload identity has impersonation permissions. (Generally, this should be the same service account to which the workload identity is bound.) +Optionally, you can specify the lifetime of the signed URLs as a second argument, which should be a `datetime.timedelta`. +If not given, the default is one hour. + The path to the Google Cloud Storage object for which to create a signed URL must be an S3 URL. The second argument to `~safir.gcs.SignedURLService.signed_url` is the MIME type of the underlying object, which will be encoded in the signed URL. diff --git a/src/safir/gcs.py b/src/safir/gcs.py index e0417dbc..9ee37bbd 100644 --- a/src/safir/gcs.py +++ b/src/safir/gcs.py @@ -22,12 +22,12 @@ class SignedURLService: Parameters ---------- - lifetime - Lifetime of the generated signed URLs. service_account The service account to use to sign the URLs. The workload identity must have access to generate service account tokens for that service account. + lifetime + Lifetime of the generated signed URLs. Notes ----- @@ -41,7 +41,9 @@ class SignedURLService: additional details on how this works. """ - def __init__(self, lifetime: timedelta, service_account: str) -> None: + def __init__( + self, service_account: str, lifetime: timedelta = timedelta(hours=1) + ) -> None: self._lifetime = lifetime self._service_account = service_account self._gcs = storage.Client() diff --git a/tests/gcs_test.py b/tests/gcs_test.py index 5afd9e4e..22efb2d4 100644 --- a/tests/gcs_test.py +++ b/tests/gcs_test.py @@ -11,12 +11,15 @@ def test_signed_url(mock_gcs: MockStorageClient) -> None: - url_service = SignedURLService(timedelta(hours=1), "service-account") + url_service = SignedURLService("service-account", timedelta(hours=1)) url = url_service.signed_url("s3://some-bucket/path/to/blob", "text/plain") assert url == "https://example.com/path/to/blob" # Test that the lifetime is passed down to the mock, which will reject it # if it's not an hour. - url_service = SignedURLService(timedelta(minutes=30), "foo") + url_service = SignedURLService("foo", timedelta(minutes=30)) with pytest.raises(AssertionError): url_service.signed_url("s3://some-bucket/blob", "text/plain") + + # Test that lifetime defaults to one hour. + url_service = SignedURLService("foo")