Allow admin to configure bucket ACL settings

To upload to Backblaze B2, the ACL needs to match bucket settings, and
if you have a CDN in front of your media server you may want to restrict
public access to the bucket to avoid expensive non-cdn transfers and
bucket enumeration.
This commit is contained in:
Charlotte 🦝 Delenk 2023-07-23 08:11:47 +01:00
parent 33e7ae7637
commit d877856527
Signed by: darkkirb
GPG key ID: AB2BD8DAF2E37122
4 changed files with 21 additions and 4 deletions

View file

@ -70,6 +70,7 @@
config :pleroma, Pleroma.Uploaders.Local, uploads: "uploads"
config :pleroma, Pleroma.Uploaders.S3,
acl: :public_read,
bucket: nil,
bucket_namespace: nil,
truncated_namespace: nil,

View file

@ -33,7 +33,7 @@ To add configuration to your config file, you can copy it from the base config.
* `federation_incoming_replies_max_depth`: Max. depth of reply-to activities fetching on incoming federation, to prevent out-of-memory situations while fetching very long threads. If set to `nil`, threads of any depth will be fetched. Lower this value if you experience out-of-memory crashes.
* `federation_reachability_timeout_days`: Timeout (in days) of each external federation target being unreachable prior to pausing federating to it.
* `allow_relay`: Permits remote instances to subscribe to all public posts of your instance. This may increase the visibility of your instance.
* `public`: Allows unauthenticated access to public resources on your instance. This is essentially used as the default value for `:restrict_unauthenticated`.
* `public`: Allows unauthenticated access to public resources on your instance. This is essentially used as the default value for `:restrict_unauthenticated`.
See `restrict_unauthenticated` for more details.
* `quarantined_instances`: *DEPRECATED* ActivityPub instances where activities will not be sent. They can still reach there via other means, we just won't send them.
* `allowed_post_formats`: MIME-type list of formats allowed to be posted (transformed into HTML).
@ -576,6 +576,7 @@ the source code is here: [kocaptcha](https://github.com/koto-bank/kocaptcha). Th
Don't forget to configure [Ex AWS S3](#ex-aws-s3-settings)
* `acl`: The ACL the uploaded media will have. By default media will be `:public_read`, and thus directly accessible from the bucket. Set this to `:private` if you have a CDN in front of your media proxy which sends authenticated requests to your S3 provider. On some providers, like Backblaze B2, this needs to match bucket settings!
* `bucket`: S3 bucket name.
* `bucket_namespace`: S3 bucket namespace.
* `truncated_namespace`: If you use S3 compatible service such as Digital Ocean Spaces or CDN, set folder name or "" etc.

View file

@ -25,6 +25,7 @@ def put_file(%Pleroma.Upload{} = upload) do
config = Config.get([__MODULE__])
bucket = Keyword.get(config, :bucket)
streaming = Keyword.get(config, :streaming_enabled)
acl = Keyword.get(config, :acl)
s3_name = strict_encode(upload.path)
@ -33,14 +34,14 @@ def put_file(%Pleroma.Upload{} = upload) do
upload.tempfile
|> ExAws.S3.Upload.stream_file()
|> ExAws.S3.upload(bucket, s3_name, [
{:acl, :public_read},
{:acl, acl},
{:content_type, upload.content_type}
])
else
{:ok, file_data} = File.read(upload.tempfile)
ExAws.S3.put_object(bucket, s3_name, file_data, [
{:acl, :public_read},
{:acl, acl},
{:content_type, upload.content_type}
])
end

View file

@ -66,7 +66,11 @@ test "it returns path with bucket namespace when namespace is set" do
end
test "save file", %{file_upload: file_upload} do
with_mock ExAws, request: fn _ -> {:ok, :ok} end do
with_mock ExAws, request: (fn _ ->
assert op.opts[:acl] == :public_read
{:ok, :ok}
end)
do
assert S3.put_file(file_upload) == {:ok, {:file, "test_folder/image-tet.jpg"}}
end
end
@ -78,6 +82,16 @@ test "returns error", %{file_upload: file_upload} do
end) =~ "Elixir.Pleroma.Uploaders.S3: {:error, \"S3 Upload failed\"}"
end
end
test "respects acl setting", %{file_upload: file_upload} do
clear_config([Pleroma.Uploaders.S3, :acl], :private)
with_mock ExAws, request: (fn(op) ->
assert op.opts[:acl] == :private
{:ok, :ok}
end) do
assert S3.put_file(file_upload) == {:ok, {:file, "test_folder/image-tet.jpg"}}
end
end
end
describe "delete_file/1" do