mirror of
https://github.com/strapi/strapi.git
synced 2025-09-27 01:09:49 +00:00
Merge pull request #15861 from strapi/private-s3-bucket/only-sign-media-from-private-bucket
This commit is contained in:
commit
13d90f66d2
@ -0,0 +1,43 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const { getBucketFromUrl } = require('../utils');
|
||||||
|
|
||||||
|
describe('Test for URLs', () => {
|
||||||
|
test('Virtual hosted style', async () => {
|
||||||
|
const url = 'https://bucket.s3.us-east-1.amazonaws.com/img.png';
|
||||||
|
const { bucket } = getBucketFromUrl(url);
|
||||||
|
expect(bucket).toEqual('bucket');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Path style', () => {
|
||||||
|
test('No key', async () => {
|
||||||
|
const url = 'https://s3.us-east-1.amazonaws.com/bucket';
|
||||||
|
const { bucket } = getBucketFromUrl(url);
|
||||||
|
expect(bucket).toEqual('bucket');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('With trailing slash', async () => {
|
||||||
|
const url = 'https://s3.us-east-1.amazonaws.com/bucket/';
|
||||||
|
const { bucket } = getBucketFromUrl(url);
|
||||||
|
expect(bucket).toEqual('bucket');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('With key', async () => {
|
||||||
|
const url = 'https://s3.us-east-1.amazonaws.com/bucket/img.png';
|
||||||
|
const { bucket } = getBucketFromUrl(url);
|
||||||
|
expect(bucket).toEqual('bucket');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('S3 access point', async () => {
|
||||||
|
const url = 'https://bucket.s3-accesspoint.us-east-1.amazonaws.com';
|
||||||
|
const { bucket } = getBucketFromUrl(url);
|
||||||
|
expect(bucket).toEqual('bucket');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('S3://', async () => {
|
||||||
|
const url = 'S3://bucket/img.png';
|
||||||
|
const { bucket } = getBucketFromUrl(url);
|
||||||
|
expect(bucket).toEqual('bucket');
|
||||||
|
});
|
||||||
|
});
|
@ -8,6 +8,7 @@
|
|||||||
// Public node modules.
|
// Public node modules.
|
||||||
const get = require('lodash/get');
|
const get = require('lodash/get');
|
||||||
const AWS = require('aws-sdk');
|
const AWS = require('aws-sdk');
|
||||||
|
const { getBucketFromUrl } = require('./utils');
|
||||||
|
|
||||||
function assertUrlProtocol(url) {
|
function assertUrlProtocol(url) {
|
||||||
// Regex to test protocol like "http://", "https://"
|
// Regex to test protocol like "http://", "https://"
|
||||||
@ -66,6 +67,12 @@ module.exports = {
|
|||||||
* @returns {Promise<{url: string}>}
|
* @returns {Promise<{url: string}>}
|
||||||
*/
|
*/
|
||||||
getSignedUrl(file, customParams = {}) {
|
getSignedUrl(file, customParams = {}) {
|
||||||
|
// Do not sign the url if it does not come from the same bucket.
|
||||||
|
const { bucket } = getBucketFromUrl(file.url);
|
||||||
|
if (bucket !== config.params.Bucket) {
|
||||||
|
return { url: file.url };
|
||||||
|
}
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const path = file.path ? `${file.path}/` : '';
|
const path = file.path ? `${file.path}/` : '';
|
||||||
const fileKey = `${path}${file.hash}${file.ext}`;
|
const fileKey = `${path}${file.hash}${file.ext}`;
|
||||||
|
63
packages/providers/upload-aws-s3/lib/utils.js
Normal file
63
packages/providers/upload-aws-s3/lib/utils.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ENDPOINT_PATTERN = /^(.+\.)?s3[.-]([a-z0-9-]+)\./;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the bucket name from a URL.
|
||||||
|
* See all URL formats in https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-bucket-intro.html
|
||||||
|
*
|
||||||
|
* @param {string} fileUrl - the URL to parse
|
||||||
|
* @returns {object} result
|
||||||
|
* @returns {string} result.bucket - the bucket name
|
||||||
|
* @returns {string} result.error - if any
|
||||||
|
*/
|
||||||
|
function getBucketFromUrl(fileUrl) {
|
||||||
|
const uri = new URL(fileUrl);
|
||||||
|
|
||||||
|
// S3://<bucket-name>/<key>
|
||||||
|
if (uri.protocol === 's3:') {
|
||||||
|
const bucket = uri.host;
|
||||||
|
|
||||||
|
if (!bucket) {
|
||||||
|
return { err: `Invalid S3 URI: no bucket: ${uri}` };
|
||||||
|
}
|
||||||
|
return { bucket };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!uri.host) {
|
||||||
|
return { err: `Invalid S3 URI: no hostname: ${uri}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
const matches = uri.host.match(ENDPOINT_PATTERN);
|
||||||
|
if (!matches) {
|
||||||
|
return { err: `Invalid S3 URI: hostname does not appear to be a valid S3 endpoint: ${uri}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
const prefix = matches[1];
|
||||||
|
// https://s3.amazonaws.com/<bucket-name>
|
||||||
|
if (!prefix) {
|
||||||
|
if (uri.pathname === '/') {
|
||||||
|
return { bucket: null };
|
||||||
|
}
|
||||||
|
|
||||||
|
const index = uri.pathname.indexOf('/', 1);
|
||||||
|
|
||||||
|
// https://s3.amazonaws.com/<bucket-name>
|
||||||
|
if (index === -1) {
|
||||||
|
return { bucket: uri.pathname.substring(1) };
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://s3.amazonaws.com/<bucket-name>/
|
||||||
|
if (index === uri.pathname.length - 1) {
|
||||||
|
return { bucket: uri.pathname.substring(1, index) };
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://s3.amazonaws.com/<bucket-name>/key
|
||||||
|
return { bucket: uri.pathname.substring(1, index) };
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://<bucket-name>.s3.amazonaws.com/
|
||||||
|
return { bucket: prefix.substring(0, prefix.length - 1) };
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { getBucketFromUrl };
|
Loading…
x
Reference in New Issue
Block a user