eslint-plugin-sonarjs
Version:
SonarJS rules for ESLint
101 lines (100 loc) • 4.3 kB
JavaScript
/*
* SonarQube JavaScript Plugin
* Copyright (C) 2011-2025 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the Sonar Source-Available License for more details.
*
* You should have received a copy of the Sonar Source-Available License
* along with this program; if not, see https://sonarsource.com/license/ssal/
*/
// https://sonarsource.github.io/rspec/#/rspec/S6303/javascript
Object.defineProperty(exports, "__esModule", { value: true });
exports.rule = void 0;
const index_js_1 = require("../helpers/index.js");
const cdk_js_1 = require("../helpers/aws/cdk.js");
const meta_js_1 = require("./meta.js");
const CfnDBCluster = 'CfnDBCluster';
const CfnDBInstance = 'CfnDBInstance';
const DatabaseCluster = 'DatabaseCluster';
const DatabaseClusterFromSnapshot = 'DatabaseClusterFromSnapshot';
const DatabaseInstance = 'DatabaseInstance';
const DatabaseInstanceReadReplica = 'DatabaseInstanceReadReplica';
exports.rule = (0, cdk_js_1.AwsCdkTemplate)({
'aws-cdk-lib.aws_rds.CfnDBCluster': checkStorage(CfnDBCluster),
'aws-cdk-lib.aws_rds.CfnDBInstance': checkStorage(CfnDBInstance),
'aws-cdk-lib.aws_rds.DatabaseCluster': checkStorage(DatabaseCluster),
'aws-cdk-lib.aws_rds.DatabaseClusterFromSnapshot': checkStorage(DatabaseClusterFromSnapshot),
'aws-cdk-lib.aws_rds.DatabaseInstance': checkStorage(DatabaseInstance),
'aws-cdk-lib.aws_rds.DatabaseInstanceReadReplica': checkStorage(DatabaseInstanceReadReplica),
}, (0, index_js_1.generateMeta)(meta_js_1.meta, {
messages: {
unsafe: 'Make sure that using unencrypted storage is safe here.',
omitted: 'Omitting storageEncrypted disables RDS encryption. Make sure it is safe here.',
},
}));
const PROPS_ARGUMENT_POSITION = 2;
function checkStorage(storage) {
return (expr, ctx) => {
const argument = expr.arguments[PROPS_ARGUMENT_POSITION];
const props = (0, index_js_1.getValueOfExpression)(ctx, argument, 'ObjectExpression');
if (isUnresolved(argument, props)) {
return;
}
if (props === undefined) {
report(expr.callee, 'omitted');
return;
}
if (isException(storage, props)) {
return;
}
const propertyKey = (0, index_js_1.getProperty)(props, 'storageEncrypted', ctx);
if (propertyKey === null) {
report(props, 'omitted');
}
if (!propertyKey) {
return;
}
const propertyValue = (0, index_js_1.getUniqueWriteUsageOrNode)(ctx, propertyKey.value);
if ((0, index_js_1.isFalseLiteral)(propertyValue)) {
report(propertyKey.value, 'unsafe');
return;
}
function isUnresolved(node, value) {
return node?.type === 'Identifier' && !(0, index_js_1.isUndefined)(node) && value === undefined;
}
function isException(storage, props) {
if (![
DatabaseCluster,
DatabaseClusterFromSnapshot,
DatabaseInstance,
DatabaseInstanceReadReplica,
].includes(storage)) {
return false;
}
const exceptionKey = (0, index_js_1.getProperty)(props, 'storageEncryptionKey', ctx);
if (exceptionKey == null) {
return false;
}
const exceptionValue = (0, index_js_1.getUniqueWriteUsageOrNode)(ctx, exceptionKey.value);
if (exceptionValue.type !== 'NewExpression') {
return false;
}
const fqn = (0, cdk_js_1.normalizeFQN)((0, index_js_1.getFullyQualifiedName)(ctx, exceptionValue.callee));
return fqn === 'aws_cdk_lib.aws_kms.Key' || fqn === 'aws_cdk_lib.aws_kms.Alias';
}
function report(node, messageId) {
ctx.report({
messageId,
node,
});
}
};
}
;