@strapi/provider-upload-aws-s3 5.36.0 → 5.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +3 -388
  2. package/package.json +7 -7
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  ## Links
8
8
 
9
9
  - [Strapi website](https://strapi.io/)
10
- - [Strapi documentation](https://docs.strapi.io)
10
+ - [Strapi documentation](https://docs.strapi.io/cms/configurations/media-library-providers/amazon-s3)
11
11
  - [Strapi community on Discord](https://discord.strapi.io)
12
12
  - [Strapi news on Twitter](https://twitter.com/strapijs)
13
13
 
@@ -36,7 +36,7 @@ See the [documentation about using a provider](https://docs.strapi.io/developer-
36
36
 
37
37
  If you're using the bucket as a CDN and deliver the content on a custom domain, you can get use of the `baseUrl` and `rootPath` properties to configure how your assets' urls will be saved inside Strapi.
38
38
 
39
- ### Provider Configuration
39
+ ### Basic Provider Configuration
40
40
 
41
41
  `./config/plugins.js` or `./config/plugins.ts` for TypeScript projects:
42
42
 
@@ -75,114 +75,6 @@ module.exports = ({ env }) => ({
75
75
 
76
76
  ## Extended Provider Configuration
77
77
 
78
- The `providerConfig` option provides additional features for data integrity, security, and cost optimization.
79
-
80
- ### Checksum Validation
81
-
82
- Enable automatic checksum calculation to ensure data integrity during uploads. The SDK calculates a checksum on the client side, and S3 validates it server-side.
83
-
84
- ```js
85
- providerOptions: {
86
- s3Options: { /* ... */ },
87
- providerConfig: {
88
- checksumAlgorithm: 'CRC64NVME', // Options: 'CRC32', 'CRC32C', 'SHA1', 'SHA256', 'CRC64NVME'
89
- },
90
- },
91
- ```
92
-
93
- `CRC64NVME` is recommended for best performance on modern hardware.
94
-
95
- ### Conditional Writes (Prevent Overwrites)
96
-
97
- Prevent accidental file overwrites due to race conditions by enabling conditional writes. When enabled, uploads will fail if an object with the same key already exists.
98
-
99
- ```js
100
- providerConfig: {
101
- preventOverwrite: true,
102
- },
103
- ```
104
-
105
- ### Storage Class Configuration (AWS S3 only)
106
-
107
- Optimize storage costs by specifying a storage class for uploaded objects. Use lower-cost classes for infrequently accessed data.
108
-
109
- **Note:** Storage classes are AWS S3-specific. Other S3-compatible providers (MinIO, DigitalOcean Spaces, IONOS, Wasabi) will ignore this setting.
110
-
111
- ```js
112
- providerConfig: {
113
- storageClass: 'INTELLIGENT_TIERING', // Auto-optimizes costs
114
- },
115
- ```
116
-
117
- Available storage classes (AWS S3):
118
-
119
- - `STANDARD` - Frequently accessed data (default)
120
- - `INTELLIGENT_TIERING` - Automatic cost optimization
121
- - `STANDARD_IA` - Infrequently accessed data
122
- - `ONEZONE_IA` - Infrequently accessed, single AZ
123
- - `GLACIER` - Archive storage
124
- - `DEEP_ARCHIVE` - Long-term archive
125
- - `GLACIER_IR` - Glacier Instant Retrieval
126
-
127
- ### Server-Side Encryption
128
-
129
- Configure server-side encryption for compliance requirements (GDPR, HIPAA, etc.).
130
-
131
- ```js
132
- providerConfig: {
133
- encryption: {
134
- type: 'AES256', // S3-managed encryption
135
- },
136
- },
137
- ```
138
-
139
- For KMS-managed encryption (AWS S3 only):
140
-
141
- ```js
142
- providerConfig: {
143
- encryption: {
144
- type: 'aws:kms',
145
- kmsKeyId: env('AWS_KMS_KEY_ID'),
146
- },
147
- },
148
- ```
149
-
150
- Available encryption types:
151
-
152
- - `AES256` - S3-managed keys (SSE-S3) - supported by most S3-compatible providers
153
- - `aws:kms` - AWS KMS-managed keys (SSE-KMS) - AWS S3 only
154
- - `aws:kms:dsse` - Dual-layer SSE with KMS - AWS S3 only
155
-
156
- ### Object Tagging
157
-
158
- Apply tags to uploaded objects for cost allocation, lifecycle policies, and organization.
159
-
160
- ```js
161
- providerConfig: {
162
- tags: {
163
- project: 'website',
164
- environment: 'production',
165
- team: 'backend',
166
- },
167
- },
168
- ```
169
-
170
- ### Multipart Upload Configuration
171
-
172
- Configure multipart upload behavior for large files.
173
-
174
- ```js
175
- providerConfig: {
176
- multipart: {
177
- partSize: 10 * 1024 * 1024, // 10MB per part
178
- queueSize: 4, // Number of parallel uploads
179
- leavePartsOnError: false, // Clean up on failure
180
- },
181
- },
182
- ```
183
-
184
- ### Complete Configuration Example
185
-
186
78
  ```js
187
79
  module.exports = ({ env }) => ({
188
80
  upload: {
@@ -226,281 +118,4 @@ module.exports = ({ env }) => ({
226
118
  });
227
119
  ```
228
120
 
229
- ### Configuration for a private S3 bucket and signed URLs
230
-
231
- If your bucket is configured to be private, you will need to set the `ACL` option to `private` in the `params` object. This will ensure file URLs are signed.
232
-
233
- **Note:** If you are using a CDN, the URLs will not be signed.
234
-
235
- You can also define the expiration time of the signed URL by setting the `signedUrlExpires` option in the `params` object. The default value is 15 minutes.
236
-
237
- `./config/plugins.js`
238
-
239
- ```js
240
- module.exports = ({ env }) => ({
241
- // ...
242
- upload: {
243
- config: {
244
- provider: 'aws-s3',
245
- providerOptions: {
246
- credentials: {
247
- accessKeyId: env('AWS_ACCESS_KEY_ID'),
248
- secretAccessKey: env('AWS_ACCESS_SECRET'),
249
- },
250
- region: env('AWS_REGION'),
251
- params: {
252
- ACL: 'private', // <== set ACL to private
253
- signedUrlExpires: env('AWS_SIGNED_URL_EXPIRES', 15 * 60),
254
- Bucket: env('AWS_BUCKET'),
255
- },
256
- },
257
- actionOptions: {
258
- upload: {},
259
- uploadStream: {},
260
- delete: {},
261
- },
262
- },
263
- },
264
- // ...
265
- });
266
- ```
267
-
268
- #### Configuration for S3 compatible services
269
-
270
- This plugin works with S3-compatible services by using the `endpoint` option. The provider automatically constructs correct URLs for S3-compatible services that return incorrect `Location` formats for multipart uploads (e.g. IONOS, MinIO).
271
-
272
- **Important:** Some providers require `forcePathStyle: true` in the `s3Options`. This is needed when the provider does not support virtual-hosted-style URLs (e.g. `bucket.endpoint.com`), and instead uses path-style URLs (e.g. `endpoint.com/bucket`).
273
-
274
- | Provider | `forcePathStyle` | `ACL` | Notes |
275
- | ------------------- | ---------------- | ----------------- | --------------------------------- |
276
- | IONOS | `true` | Supported | Multipart Location bug auto-fixed |
277
- | MinIO | `true` | Supported | |
278
- | Contabo | `true` | Supported | |
279
- | Hetzner | `true` | Supported | |
280
- | DigitalOcean Spaces | Not needed | Supported | |
281
- | Wasabi | Not needed | Supported | |
282
- | Scaleway | Not needed | Supported | |
283
- | Vultr | Not needed | Supported | |
284
- | Backblaze B2 | Not needed | Supported | |
285
- | Cloudflare R2 | Not needed | **Not supported** | Omit `ACL` from params |
286
-
287
- ##### Scaleway example
288
-
289
- `./config/plugins.js`
290
-
291
- ```js
292
- module.exports = ({ env }) => ({
293
- // ...
294
- upload: {
295
- config: {
296
- provider: 'aws-s3',
297
- providerOptions: {
298
- s3Options: {
299
- credentials: {
300
- accessKeyId: env('SCALEWAY_ACCESS_KEY_ID'),
301
- secretAccessKey: env('SCALEWAY_ACCESS_SECRET'),
302
- },
303
- region: env('SCALEWAY_REGION'), // e.g "fr-par"
304
- endpoint: env('SCALEWAY_ENDPOINT'), // e.g. "https://s3.fr-par.scw.cloud"
305
- params: {
306
- Bucket: env('SCALEWAY_BUCKET'),
307
- },
308
- },
309
- },
310
- },
311
- },
312
- // ...
313
- });
314
- ```
315
-
316
- ##### IONOS / MinIO / Contabo example (forcePathStyle required)
317
-
318
- ```js
319
- module.exports = ({ env }) => ({
320
- upload: {
321
- config: {
322
- provider: 'aws-s3',
323
- providerOptions: {
324
- s3Options: {
325
- credentials: {
326
- accessKeyId: env('S3_ACCESS_KEY_ID'),
327
- secretAccessKey: env('S3_ACCESS_SECRET'),
328
- },
329
- region: env('S3_REGION'),
330
- endpoint: env('S3_ENDPOINT'),
331
- forcePathStyle: true, // Required for these providers
332
- params: {
333
- Bucket: env('S3_BUCKET'),
334
- },
335
- },
336
- },
337
- },
338
- },
339
- });
340
- ```
341
-
342
- ##### Cloudflare R2 example (no ACL support)
343
-
344
- ```js
345
- module.exports = ({ env }) => ({
346
- upload: {
347
- config: {
348
- provider: 'aws-s3',
349
- providerOptions: {
350
- s3Options: {
351
- credentials: {
352
- accessKeyId: env('R2_ACCESS_KEY_ID'),
353
- secretAccessKey: env('R2_ACCESS_SECRET'),
354
- },
355
- region: 'auto',
356
- endpoint: env('R2_ENDPOINT'), // e.g. "https://<account-id>.r2.cloudflarestorage.com"
357
- params: {
358
- Bucket: env('R2_BUCKET'),
359
- // Do NOT set ACL - R2 does not support ACLs
360
- },
361
- },
362
- },
363
- },
364
- },
365
- });
366
- ```
367
-
368
- ### Security Middleware Configuration
369
-
370
- Due to the default settings in the Strapi Security Middleware you will need to modify the `contentSecurityPolicy` settings to properly see thumbnail previews in the Media Library. You should replace `strapi::security` string with the object bellow instead as explained in the [middleware configuration](https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/required/middlewares.html#loading-order) documentation.
371
-
372
- `./config/middlewares.js`
373
-
374
- ```js
375
- module.exports = [
376
- // ...
377
- {
378
- name: 'strapi::security',
379
- config: {
380
- contentSecurityPolicy: {
381
- useDefaults: true,
382
- directives: {
383
- 'connect-src': ["'self'", 'https:'],
384
- 'img-src': [
385
- "'self'",
386
- 'data:',
387
- 'blob:',
388
- 'market-assets.strapi.io',
389
- 'yourBucketName.s3.yourRegion.amazonaws.com',
390
- ],
391
- 'media-src': [
392
- "'self'",
393
- 'data:',
394
- 'blob:',
395
- 'market-assets.strapi.io',
396
- 'yourBucketName.s3.yourRegion.amazonaws.com',
397
- ],
398
- upgradeInsecureRequests: null,
399
- },
400
- },
401
- },
402
- },
403
- // ...
404
- ];
405
- ```
406
-
407
- If you use dots in your bucket name (`forcePathStyle set to false`), the url of the resource is in directory style (`s3.yourRegion.amazonaws.com/your.bucket.name/image.jpg`) instead of `yourBucketName.s3.yourRegion.amazonaws.com/image.jpg` so in that case the img-src and media-src directives to add will be `s3.yourRegion.amazonaws.com` without the bucket name in the url.
408
-
409
- ## Bucket CORS Configuration
410
-
411
- If you are planning on uploading content like GIFs and videos to your S3 bucket, you will want to edit its CORS configuration so that thumbnails are properly shown in Strapi. To do so, open your Bucket on the AWS console and locate the _Cross-origin resource sharing (CORS)_ field under the _Permissions_ tab, then amend the policies by writing your own JSON configuration, or copying and pasting the following one:
412
-
413
- ```json
414
- [
415
- {
416
- "AllowedHeaders": ["*"],
417
- "AllowedMethods": ["GET"],
418
- "AllowedOrigins": ["YOUR STRAPI URL"],
419
- "ExposeHeaders": [],
420
- "MaxAgeSeconds": 3000
421
- }
422
- ]
423
- ```
424
-
425
- ## Required AWS Policy Actions
426
-
427
- These are the minimum amount of permissions needed for this provider to work.
428
-
429
- ```json
430
- "Action": [
431
- "s3:PutObject",
432
- "s3:GetObject",
433
- "s3:ListBucket",
434
- "s3:DeleteObject",
435
- "s3:PutObjectAcl"
436
- ],
437
- ```
438
-
439
- ## Update to AWS SDK V3 and URL Format Change
440
-
441
- In the recent update of the `@strapi/provider-upload-aws-s3` plugin, we have transitioned from AWS SDK V2 to AWS SDK V3. This significant update brings along a change in the format of the URLs used in Amazon S3 services.
442
-
443
- ### Understanding the New URL Format
444
-
445
- AWS SDK V3 adopts the virtual-hosted–style URI format for S3 URLs. This format is recommended by AWS and is likely to become required in the near future, as the path-style URI is being deprecated. More details on this format can be found in the [AWS User Guide](https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html#virtual-hosted-style-access).
446
-
447
- ### Why the Change?
448
-
449
- The move to virtual-hosted–style URIs aligns with AWS's recommendation and future-proofing strategies. For an in-depth understanding of AWS's decision behind this transition, you can refer to their detailed post [here](https://aws.amazon.com/es/blogs/aws/amazon-s3-path-deprecation-plan-the-rest-of-the-story/).
450
-
451
- ### Configuring Your Strapi Application
452
-
453
- If you wish to continue using the plugin with Strapi 4.15.x versions or newer without changing your URL format, it's possible to specify your desired URL format directly in the plugin's configuration. Below is an example configuration highlighting the critical `baseUrl` property:
454
-
455
- ```javascript
456
- upload: {
457
- config: {
458
- provider: 'aws-s3',
459
- providerOptions: {
460
- credentials: {
461
- accessKeyId: process.env.AWS_ACCESS_KEY_ID,
462
- secretAccessKey: process.env.AWS_ACCESS_SECRET,
463
- },
464
- region: process.env.AWS_REGION,
465
- baseUrl: `https://s3.${region}.amazonaws.com/${bucket}`, // This line sets the custom url format
466
- params: {
467
- ACL: process.env.AWS_ACL || 'public-read',
468
- signedUrlExpires: process.env.AWS_SIGNED_URL_EXPIRES || 15 * 60,
469
- Bucket: process.env.AWS_BUCKET,
470
- },
471
- },
472
- actionOptions: {
473
- upload: {},
474
- uploadStream: {},
475
- delete: {},
476
- },
477
- },
478
- }
479
- ```
480
-
481
- This configuration ensures compatibility with the updated AWS SDK while providing flexibility in URL format selection, catering to various user needs.
482
-
483
- ## Security Considerations
484
-
485
- This provider includes several security measures to protect against common attack vectors.
486
-
487
- ### Path Traversal Prevention
488
-
489
- File paths, hashes, and extensions are sanitized to prevent directory traversal attacks. Sequences like `../` are removed, and special characters in file extensions are filtered.
490
-
491
- ### Parameter Injection Protection
492
-
493
- The `customParams` option allows passing additional parameters to S3 operations. However, critical security parameters (`Bucket`, `Key`, `Body`) cannot be overridden via `customParams` to prevent unauthorized access to other buckets or objects.
494
-
495
- ### URL Protocol Validation
496
-
497
- Only `http://` and `https://` protocols are accepted for S3 response URLs. This prevents potential injection of dangerous protocols like `file://`, `javascript:`, or `data:`.
498
-
499
- ### Recommendations
500
-
501
- 1. **Use Private ACL**: Set `ACL: 'private'` for sensitive content and use signed URLs for access.
502
- 2. **Enable Encryption**: Configure server-side encryption for data at rest.
503
- 3. **Enable Checksums**: Use `checksumAlgorithm` to ensure data integrity during uploads.
504
- 4. **Use Conditional Writes**: Enable `preventOverwrite: true` to prevent accidental overwrites.
505
- 5. **Apply Least Privilege**: Use the minimum required IAM permissions listed above.
506
- 6. **Enable Bucket Versioning**: Consider enabling S3 versioning for recovery from accidental deletions.
121
+ Many additional configuration options and best practices are described in the [official documentation](https://docs.strapi.io//cms/configurations/media-library-providers/amazon-s3)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/provider-upload-aws-s3",
3
- "version": "5.36.0",
3
+ "version": "5.37.0",
4
4
  "description": "AWS S3 provider for strapi upload",
5
5
  "keywords": [
6
6
  "upload",
@@ -47,16 +47,16 @@
47
47
  "watch": "run -T rollup -c -w"
48
48
  },
49
49
  "dependencies": {
50
- "@aws-sdk/client-s3": "3.975.0",
51
- "@aws-sdk/lib-storage": "3.975.0",
52
- "@aws-sdk/s3-request-presigner": "3.975.0",
53
- "@aws-sdk/types": "3.973.0",
50
+ "@aws-sdk/client-s3": "3.995.0",
51
+ "@aws-sdk/lib-storage": "3.995.0",
52
+ "@aws-sdk/s3-request-presigner": "3.995.0",
53
+ "@aws-sdk/types": "3.973.1",
54
54
  "lodash": "4.17.23"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@types/jest": "29.5.2",
58
- "eslint-config-custom": "5.36.0",
59
- "tsconfig": "5.36.0"
58
+ "eslint-config-custom": "5.37.0",
59
+ "tsconfig": "5.37.0"
60
60
  },
61
61
  "engines": {
62
62
  "node": ">=20.0.0 <=24.x.x",