mirror of
https://github.com/strapi/strapi.git
synced 2025-09-19 21:38:05 +00:00
Merge pull request #15935 from strapi/data-transfer/disable-transfer-when-missing-salt
This commit is contained in:
commit
03cb2b91ae
26
packages/core/admin/server/middlewares/data-transfer.js
Normal file
26
packages/core/admin/server/middlewares/data-transfer.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const { getService } = require('../utils');
|
||||||
|
|
||||||
|
module.exports = () => async (ctx, next) => {
|
||||||
|
const transferUtils = getService('transfer').utils;
|
||||||
|
|
||||||
|
const { hasValidTokenSalt, isDataTransferEnabled, isDisabledFromEnv } = transferUtils;
|
||||||
|
|
||||||
|
if (isDataTransferEnabled()) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasValidTokenSalt()) {
|
||||||
|
return ctx.notImplemented(
|
||||||
|
'The server configuration for data transfer is invalid. Please contact your server administrator.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDisabledFromEnv()) {
|
||||||
|
return ctx.notFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should never happen as long as we're handling individual scenarios above
|
||||||
|
throw new Error('Unexpected error while trying to access a data transfer route');
|
||||||
|
};
|
@ -4,4 +4,5 @@ const rateLimit = require('./rateLimit');
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
rateLimit,
|
rateLimit,
|
||||||
|
'data-transfer': require('./data-transfer'),
|
||||||
};
|
};
|
||||||
|
@ -9,15 +9,7 @@ module.exports = [
|
|||||||
path: '/transfer/runner/connect',
|
path: '/transfer/runner/connect',
|
||||||
handler: 'transfer.runner-connect',
|
handler: 'transfer.runner-connect',
|
||||||
config: {
|
config: {
|
||||||
middlewares: [
|
middlewares: ['admin::data-transfer'],
|
||||||
(ctx, next) => {
|
|
||||||
if (process.env.STRAPI_DISABLE_REMOTE_DATA_TRANSFER === 'true') {
|
|
||||||
return ctx.notFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
return next();
|
|
||||||
},
|
|
||||||
],
|
|
||||||
// TODO: Allow not passing any scope <> Add a way to prevent assigning one by default
|
// TODO: Allow not passing any scope <> Add a way to prevent assigning one by default
|
||||||
auth: { strategies: [dataTransferAuthStrategy], scope: ['push'] },
|
auth: { strategies: [dataTransferAuthStrategy], scope: ['push'] },
|
||||||
},
|
},
|
||||||
@ -28,6 +20,7 @@ module.exports = [
|
|||||||
path: '/transfer/tokens',
|
path: '/transfer/tokens',
|
||||||
handler: 'transfer.token-create',
|
handler: 'transfer.token-create',
|
||||||
config: {
|
config: {
|
||||||
|
middlewares: ['admin::data-transfer'],
|
||||||
policies: [
|
policies: [
|
||||||
'admin::isAuthenticatedAdmin',
|
'admin::isAuthenticatedAdmin',
|
||||||
{ name: 'admin::hasPermissions', config: { actions: ['admin::transfer.tokens.create'] } },
|
{ name: 'admin::hasPermissions', config: { actions: ['admin::transfer.tokens.create'] } },
|
||||||
@ -39,6 +32,7 @@ module.exports = [
|
|||||||
path: '/transfer/tokens',
|
path: '/transfer/tokens',
|
||||||
handler: 'transfer.token-list',
|
handler: 'transfer.token-list',
|
||||||
config: {
|
config: {
|
||||||
|
middlewares: ['admin::data-transfer'],
|
||||||
policies: [
|
policies: [
|
||||||
'admin::isAuthenticatedAdmin',
|
'admin::isAuthenticatedAdmin',
|
||||||
{ name: 'admin::hasPermissions', config: { actions: ['admin::transfer.tokens.read'] } },
|
{ name: 'admin::hasPermissions', config: { actions: ['admin::transfer.tokens.read'] } },
|
||||||
@ -50,6 +44,7 @@ module.exports = [
|
|||||||
path: '/transfer/tokens/:id',
|
path: '/transfer/tokens/:id',
|
||||||
handler: 'transfer.token-revoke',
|
handler: 'transfer.token-revoke',
|
||||||
config: {
|
config: {
|
||||||
|
middlewares: ['admin::data-transfer'],
|
||||||
policies: [
|
policies: [
|
||||||
'admin::isAuthenticatedAdmin',
|
'admin::isAuthenticatedAdmin',
|
||||||
{ name: 'admin::hasPermissions', config: { actions: ['admin::transfer.tokens.delete'] } },
|
{ name: 'admin::hasPermissions', config: { actions: ['admin::transfer.tokens.delete'] } },
|
||||||
@ -61,6 +56,7 @@ module.exports = [
|
|||||||
path: '/transfer/tokens/:id',
|
path: '/transfer/tokens/:id',
|
||||||
handler: 'transfer.token-getById',
|
handler: 'transfer.token-getById',
|
||||||
config: {
|
config: {
|
||||||
|
middlewares: ['admin::data-transfer'],
|
||||||
policies: [
|
policies: [
|
||||||
'admin::isAuthenticatedAdmin',
|
'admin::isAuthenticatedAdmin',
|
||||||
{ name: 'admin::hasPermissions', config: { actions: ['admin::transfer.tokens.read'] } },
|
{ name: 'admin::hasPermissions', config: { actions: ['admin::transfer.tokens.read'] } },
|
||||||
@ -72,6 +68,7 @@ module.exports = [
|
|||||||
path: '/transfer/tokens/:id',
|
path: '/transfer/tokens/:id',
|
||||||
handler: 'transfer.token-update',
|
handler: 'transfer.token-update',
|
||||||
config: {
|
config: {
|
||||||
|
middlewares: ['admin::data-transfer'],
|
||||||
policies: [
|
policies: [
|
||||||
'admin::isAuthenticatedAdmin',
|
'admin::isAuthenticatedAdmin',
|
||||||
{ name: 'admin::hasPermissions', config: { actions: ['admin::transfer.tokens.update'] } },
|
{ name: 'admin::hasPermissions', config: { actions: ['admin::transfer.tokens.update'] } },
|
||||||
@ -83,6 +80,7 @@ module.exports = [
|
|||||||
path: '/transfer/tokens/:id/regenerate',
|
path: '/transfer/tokens/:id/regenerate',
|
||||||
handler: 'transfer.token-regenerate',
|
handler: 'transfer.token-regenerate',
|
||||||
config: {
|
config: {
|
||||||
|
middlewares: ['admin::data-transfer'],
|
||||||
policies: [
|
policies: [
|
||||||
'admin::isAuthenticatedAdmin',
|
'admin::isAuthenticatedAdmin',
|
||||||
{
|
{
|
||||||
|
@ -3,4 +3,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
permission: require('./permission'),
|
permission: require('./permission'),
|
||||||
token: require('./token'),
|
token: require('./token'),
|
||||||
|
utils: require('./utils'),
|
||||||
};
|
};
|
||||||
|
@ -8,6 +8,7 @@ const {
|
|||||||
} = require('@strapi/utils');
|
} = require('@strapi/utils');
|
||||||
|
|
||||||
const constants = require('../constants');
|
const constants = require('../constants');
|
||||||
|
const { getService } = require('../../utils');
|
||||||
|
|
||||||
const TRANSFER_TOKEN_UID = 'admin::transfer-token';
|
const TRANSFER_TOKEN_UID = 'admin::transfer-token';
|
||||||
const TRANSFER_TOKEN_PERMISSION_UID = 'admin::transfer-token-permission';
|
const TRANSFER_TOKEN_PERMISSION_UID = 'admin::transfer-token-permission';
|
||||||
@ -327,6 +328,12 @@ const getExpirationFields = (lifespan) => {
|
|||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
const hash = (accessKey) => {
|
const hash = (accessKey) => {
|
||||||
|
const { hasValidTokenSalt } = getService('transfer').utils;
|
||||||
|
|
||||||
|
if (!hasValidTokenSalt()) {
|
||||||
|
throw new TypeError('Required token salt is not defined');
|
||||||
|
}
|
||||||
|
|
||||||
return crypto
|
return crypto
|
||||||
.createHmac('sha512', strapi.config.get('admin.transfer.token.salt'))
|
.createHmac('sha512', strapi.config.get('admin.transfer.token.salt'))
|
||||||
.update(accessKey)
|
.update(accessKey)
|
||||||
@ -337,9 +344,17 @@ const hash = (accessKey) => {
|
|||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const checkSaltIsDefined = () => {
|
const checkSaltIsDefined = () => {
|
||||||
if (!strapi.config.get('admin.transfer.token.salt')) {
|
const { hasValidTokenSalt, isDisabledFromEnv } = getService('transfer').utils;
|
||||||
throw new Error(
|
|
||||||
`Missing transfer.token.salt. Please set transfer.token.salt in config/admin.js (ex: you can generate one using Node with \`crypto.randomBytes(16).toString('base64')\`).
|
// Ignore the check if the data-transfer feature is manually disabled
|
||||||
|
if (isDisabledFromEnv()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasValidTokenSalt()) {
|
||||||
|
process.emitWarning(
|
||||||
|
`Missing transfer.token.salt: Data transfer features have been disabled.
|
||||||
|
Please set transfer.token.salt in config/admin.js (ex: you can generate one using Node with \`crypto.randomBytes(16).toString('base64')\`)
|
||||||
For security reasons, prefer storing the secret in an environment variable and read it in config/admin.js. See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`
|
For security reasons, prefer storing the secret in an environment variable and read it in config/admin.js. See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
38
packages/core/admin/server/services/transfer/utils.js
Normal file
38
packages/core/admin/server/services/transfer/utils.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const { env } = require('@strapi/utils');
|
||||||
|
|
||||||
|
const { getService } = require('../../utils');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the data transfer features have been disabled from the env configuration
|
||||||
|
*
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
const isDisabledFromEnv = () => {
|
||||||
|
return env.bool('STRAPI_DISABLE_REMOTE_DATA_TRANSFER', false);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A valid transfer token salt must be a non-empty string defined in the Strapi config
|
||||||
|
*
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
const hasValidTokenSalt = () => {
|
||||||
|
const salt = strapi.config.get('admin.transfer.token.salt', null);
|
||||||
|
|
||||||
|
return typeof salt === 'string' && salt.length > 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether data transfer features are enabled
|
||||||
|
*
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
const isDataTransferEnabled = () => {
|
||||||
|
const { utils } = getService('transfer');
|
||||||
|
|
||||||
|
return !utils.isDisabledFromEnv() && utils.hasValidTokenSalt();
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = { isDataTransferEnabled, isDisabledFromEnv, hasValidTokenSalt };
|
Loading…
x
Reference in New Issue
Block a user