diff options
author | Doug Luce <doug@github.con.com> | 2022-03-15 08:57:12 -0700 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2022-03-16 10:58:01 +0100 |
commit | f9915efa5ea0714178fc60d11a0d5434e7b1e600 (patch) | |
tree | cf2e7249a64a4af73a89aa19c755d5eec0ab9fe2 | |
parent | 60233e90d280eb865d396b30b63c0e88d13ca7db (diff) | |
download | PeerTube-f9915efa5ea0714178fc60d11a0d5434e7b1e600.tar.gz PeerTube-f9915efa5ea0714178fc60d11a0d5434e7b1e600.tar.zst PeerTube-f9915efa5ea0714178fc60d11a0d5434e7b1e600.zip |
Make object storage ACL configurable
Override this value to allow uploads to non-public S3
buckets. Otherwise "AccessDenied: Access Denied" errors will end up in
the log.
Fixes #4850
-rw-r--r-- | config/default.yaml | 3 | ||||
-rw-r--r-- | config/production.yaml.example | 3 | ||||
-rw-r--r-- | server/initializers/config.ts | 1 | ||||
-rw-r--r-- | server/lib/object-storage/shared/object-storage-helpers.ts | 28 | ||||
-rw-r--r-- | support/docker/production/config/custom-environment-variables.yaml | 1 |
5 files changed, 28 insertions, 8 deletions
diff --git a/config/default.yaml b/config/default.yaml index 42ce12c18..6db8d3803 100644 --- a/config/default.yaml +++ b/config/default.yaml | |||
@@ -138,6 +138,9 @@ object_storage: | |||
138 | 138 | ||
139 | region: 'us-east-1' | 139 | region: 'us-east-1' |
140 | 140 | ||
141 | # Set this ACL on each uploaded object | ||
142 | upload_acl: 'public-read' | ||
143 | |||
141 | credentials: | 144 | credentials: |
142 | # You can also use AWS_ACCESS_KEY_ID env variable | 145 | # You can also use AWS_ACCESS_KEY_ID env variable |
143 | access_key_id: '' | 146 | access_key_id: '' |
diff --git a/config/production.yaml.example b/config/production.yaml.example index bb1b4615b..e6e85da12 100644 --- a/config/production.yaml.example +++ b/config/production.yaml.example | |||
@@ -134,6 +134,9 @@ object_storage: | |||
134 | 134 | ||
135 | region: 'us-east-1' | 135 | region: 'us-east-1' |
136 | 136 | ||
137 | # Set this ACL on each uploaded object | ||
138 | upload_acl: 'public' | ||
139 | |||
137 | credentials: | 140 | credentials: |
138 | # You can also use AWS_ACCESS_KEY_ID env variable | 141 | # You can also use AWS_ACCESS_KEY_ID env variable |
139 | access_key_id: '' | 142 | access_key_id: '' |
diff --git a/server/initializers/config.ts b/server/initializers/config.ts index 3aadd9cbd..1658298c5 100644 --- a/server/initializers/config.ts +++ b/server/initializers/config.ts | |||
@@ -114,6 +114,7 @@ const CONFIG = { | |||
114 | MAX_UPLOAD_PART: bytes.parse(config.get<string>('object_storage.max_upload_part')), | 114 | MAX_UPLOAD_PART: bytes.parse(config.get<string>('object_storage.max_upload_part')), |
115 | ENDPOINT: config.get<string>('object_storage.endpoint'), | 115 | ENDPOINT: config.get<string>('object_storage.endpoint'), |
116 | REGION: config.get<string>('object_storage.region'), | 116 | REGION: config.get<string>('object_storage.region'), |
117 | UPLOAD_ACL: config.get<string>('object_storage.upload_acl'), | ||
117 | CREDENTIALS: { | 118 | CREDENTIALS: { |
118 | ACCESS_KEY_ID: config.get<string>('object_storage.credentials.access_key_id'), | 119 | ACCESS_KEY_ID: config.get<string>('object_storage.credentials.access_key_id'), |
119 | SECRET_ACCESS_KEY: config.get<string>('object_storage.credentials.secret_access_key') | 120 | SECRET_ACCESS_KEY: config.get<string>('object_storage.credentials.secret_access_key') |
diff --git a/server/lib/object-storage/shared/object-storage-helpers.ts b/server/lib/object-storage/shared/object-storage-helpers.ts index 47c37ffda..ecb82856e 100644 --- a/server/lib/object-storage/shared/object-storage-helpers.ts +++ b/server/lib/object-storage/shared/object-storage-helpers.ts | |||
@@ -6,10 +6,12 @@ import { | |||
6 | CompletedPart, | 6 | CompletedPart, |
7 | CompleteMultipartUploadCommand, | 7 | CompleteMultipartUploadCommand, |
8 | CreateMultipartUploadCommand, | 8 | CreateMultipartUploadCommand, |
9 | CreateMultipartUploadCommandInput, | ||
9 | DeleteObjectCommand, | 10 | DeleteObjectCommand, |
10 | GetObjectCommand, | 11 | GetObjectCommand, |
11 | ListObjectsV2Command, | 12 | ListObjectsV2Command, |
12 | PutObjectCommand, | 13 | PutObjectCommand, |
14 | PutObjectCommandInput, | ||
13 | UploadPartCommand | 15 | UploadPartCommand |
14 | } from '@aws-sdk/client-s3' | 16 | } from '@aws-sdk/client-s3' |
15 | import { pipelinePromise } from '@server/helpers/core-utils' | 17 | import { pipelinePromise } from '@server/helpers/core-utils' |
@@ -143,12 +145,17 @@ async function objectStoragePut (options: { | |||
143 | }) { | 145 | }) { |
144 | const { objectStorageKey, content, bucketInfo } = options | 146 | const { objectStorageKey, content, bucketInfo } = options |
145 | 147 | ||
146 | const command = new PutObjectCommand({ | 148 | const input: PutObjectCommandInput = { |
147 | Bucket: bucketInfo.BUCKET_NAME, | 149 | Bucket: bucketInfo.BUCKET_NAME, |
148 | Key: buildKey(objectStorageKey, bucketInfo), | 150 | Key: buildKey(objectStorageKey, bucketInfo), |
149 | Body: content, | 151 | Body: content |
150 | ACL: 'public-read' | 152 | } |
151 | }) | 153 | |
154 | if (CONFIG.OBJECT_STORAGE.UPLOAD_ACL) { | ||
155 | input.ACL = CONFIG.OBJECT_STORAGE.UPLOAD_ACL | ||
156 | } | ||
157 | |||
158 | const command = new PutObjectCommand(input) | ||
152 | 159 | ||
153 | await getClient().send(command) | 160 | await getClient().send(command) |
154 | 161 | ||
@@ -167,11 +174,16 @@ async function multiPartUpload (options: { | |||
167 | 174 | ||
168 | const statResult = await stat(inputPath) | 175 | const statResult = await stat(inputPath) |
169 | 176 | ||
170 | const createMultipartCommand = new CreateMultipartUploadCommand({ | 177 | const input: CreateMultipartUploadCommandInput = { |
171 | Bucket: bucketInfo.BUCKET_NAME, | 178 | Bucket: bucketInfo.BUCKET_NAME, |
172 | Key: key, | 179 | Key: buildKey(objectStorageKey, bucketInfo) |
173 | ACL: 'public-read' | 180 | } |
174 | }) | 181 | |
182 | if (CONFIG.OBJECT_STORAGE.UPLOAD_ACL) { | ||
183 | input.ACL = CONFIG.OBJECT_STORAGE.UPLOAD_ACL | ||
184 | } | ||
185 | |||
186 | const createMultipartCommand = new CreateMultipartUploadCommand(input) | ||
175 | const createResponse = await s3Client.send(createMultipartCommand) | 187 | const createResponse = await s3Client.send(createMultipartCommand) |
176 | 188 | ||
177 | const fd = await open(inputPath, 'r') | 189 | const fd = await open(inputPath, 'r') |
diff --git a/support/docker/production/config/custom-environment-variables.yaml b/support/docker/production/config/custom-environment-variables.yaml index 32552964d..9c84428b7 100644 --- a/support/docker/production/config/custom-environment-variables.yaml +++ b/support/docker/production/config/custom-environment-variables.yaml | |||
@@ -66,6 +66,7 @@ object_storage: | |||
66 | bucket_name: "PEERTUBE_OBJECT_STORAGE_STREAMING_PLAYLISTS_BUCKET_NAME" | 66 | bucket_name: "PEERTUBE_OBJECT_STORAGE_STREAMING_PLAYLISTS_BUCKET_NAME" |
67 | prefix: "PEERTUBE_OBJECT_STORAGE_STREAMING_PLAYLISTS_PREFIX" | 67 | prefix: "PEERTUBE_OBJECT_STORAGE_STREAMING_PLAYLISTS_PREFIX" |
68 | base_url: "PEERTUBE_OBJECT_STORAGE_STREAMING_PLAYLISTS_BASE_URL" | 68 | base_url: "PEERTUBE_OBJECT_STORAGE_STREAMING_PLAYLISTS_BASE_URL" |
69 | upload_acl: "PEERTUBE_OBJECT_STORAGE_UPLOAD_ACL" | ||
69 | 70 | ||
70 | videos: | 71 | videos: |
71 | bucket_name: "PEERTUBE_OBJECT_STORAGE_VIDEOS_BUCKET_NAME" | 72 | bucket_name: "PEERTUBE_OBJECT_STORAGE_VIDEOS_BUCKET_NAME" |