-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch '8.x' into ua/security-soln-logsdb-callout
- Loading branch information
Showing
205 changed files
with
32,336 additions
and
1,416 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,7 +40,7 @@ main () { | |
git config --global user.name "$KIBANA_MACHINE_USERNAME" | ||
git config --global user.email '[email protected]' | ||
|
||
PR_TITLE="[Console] Update console definitions (${branch_name})" | ||
PR_TITLE="[Console] Update console definitions (${BUILDKITE_BRANCH})" | ||
PR_BODY='This PR updates the console definitions to match the latest ones from the @elastic/elasticsearch-specification repo.' | ||
|
||
# Check if a PR already exists | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -581,6 +581,7 @@ | |
"@kbn/inference-common": "link:x-pack/platform/packages/shared/ai-infra/inference-common", | ||
"@kbn/inference-endpoint-plugin": "link:x-pack/platform/plugins/shared/inference_endpoint", | ||
"@kbn/inference-endpoint-ui-common": "link:x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common", | ||
"@kbn/inference-langchain": "link:x-pack/platform/packages/shared/ai-infra/inference-langchain", | ||
"@kbn/inference-plugin": "link:x-pack/platform/plugins/shared/inference", | ||
"@kbn/inference_integration_flyout": "link:x-pack/platform/packages/private/ml/inference_integration_flyout", | ||
"@kbn/infra-forge": "link:x-pack/platform/packages/private/kbn-infra-forge", | ||
|
@@ -1233,7 +1234,7 @@ | |
"react-popper-tooltip": "^4.4.2", | ||
"react-recompose": "^0.33.0", | ||
"react-redux": "^7.2.8", | ||
"react-reverse-portal": "^2.1.2", | ||
"react-reverse-portal": "^2.2.0", | ||
"react-router": "^5.3.4", | ||
"react-router-config": "^5.1.1", | ||
"react-router-dom": "^5.3.4", | ||
|
@@ -1304,7 +1305,8 @@ | |
"yaml": "^2.5.1", | ||
"yauzl": "^2.10.0", | ||
"yazl": "^2.5.1", | ||
"zod": "^3.22.3" | ||
"zod": "^3.22.3", | ||
"zod-to-json-schema": "^3.23.0" | ||
}, | ||
"devDependencies": { | ||
"@apidevtools/swagger-parser": "^10.1.1", | ||
|
@@ -1877,8 +1879,7 @@ | |
"xml-crypto": "^6.0.0", | ||
"xmlbuilder": "13.0.2", | ||
"yargs": "^15.4.1", | ||
"yarn-deduplicate": "^6.0.2", | ||
"zod-to-json-schema": "^3.23.0" | ||
"yarn-deduplicate": "^6.0.2" | ||
}, | ||
"packageManager": "[email protected]" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
223 changes: 223 additions & 0 deletions
223
packages/kbn-eslint-plugin-eslint/rules/require_kibana_feature_privileges_naming.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,223 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the "Elastic License | ||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side | ||
* Public License v 1"; you may not use this file except in compliance with, at | ||
* your election, the "Elastic License 2.0", the "GNU Affero General Public | ||
* License v3.0 only", or the "Server Side Public License, v 1". | ||
*/ | ||
|
||
const ts = require('typescript'); | ||
const path = require('path'); | ||
|
||
function getImportedVariableValue(context, name, propertyName) { | ||
const parent = context | ||
.getAncestors() | ||
.find((ancestor) => ['BlockStatement', 'Program'].includes(ancestor.type)); | ||
|
||
if (!parent) return; | ||
|
||
const importDeclaration = parent.body.find( | ||
(statement) => | ||
statement.type === 'ImportDeclaration' && | ||
statement.specifiers.some((specifier) => specifier.local.name === name) | ||
); | ||
|
||
if (!importDeclaration) return; | ||
|
||
const absoluteImportPath = require.resolve(importDeclaration.source.value, { | ||
paths: [path.dirname(context.getFilename())], | ||
}); | ||
|
||
const program = ts.createProgram([absoluteImportPath], {}); | ||
const sourceFile = program.getSourceFile(absoluteImportPath); | ||
|
||
if (!sourceFile) return null; | ||
|
||
const checker = program.getTypeChecker(); | ||
const symbols = checker.getExportsOfModule(sourceFile.symbol); | ||
const symbol = symbols.find((s) => s.name === name); | ||
|
||
if (!symbol) return null; | ||
|
||
if (propertyName) { | ||
const currentSymbol = checker.getTypeOfSymbolAtLocation(symbol, sourceFile); | ||
const property = currentSymbol.getProperty(propertyName); | ||
|
||
if (ts.isStringLiteral(property.valueDeclaration.initializer)) { | ||
return property.valueDeclaration.initializer.text; | ||
} | ||
|
||
return null; | ||
} | ||
|
||
const initializer = symbol?.valueDeclaration?.initializer; | ||
|
||
if (ts.isStringLiteral(initializer)) { | ||
return initializer.text; | ||
} | ||
|
||
return null; | ||
} | ||
|
||
function validatePrivilegesNode(context, privilegesNode, scopedVariables) { | ||
['all', 'read'].forEach((privilegeType) => { | ||
const privilege = privilegesNode.value.properties.find( | ||
(prop) => | ||
prop.key && prop.key.name === privilegeType && prop.value.type === 'ObjectExpression' | ||
); | ||
|
||
if (!privilege) return; | ||
|
||
const apiProperty = privilege.value.properties.find( | ||
(prop) => prop.key && prop.key.name === 'api' && prop.value.type === 'ArrayExpression' | ||
); | ||
|
||
if (!apiProperty) return; | ||
|
||
apiProperty.value.elements.forEach((element) => { | ||
let valueToCheck = null; | ||
|
||
if (element.type === 'Literal' && typeof element.value === 'string') { | ||
valueToCheck = element.value; | ||
} else if (element.type === 'Identifier') { | ||
valueToCheck = scopedVariables.has(element.name) | ||
? scopedVariables.get(element.name) | ||
: getImportedVariableValue(context, element.name); | ||
} else if (element.type === 'MemberExpression') { | ||
valueToCheck = getImportedVariableValue( | ||
context, | ||
element.object.name, | ||
element.property.name | ||
); | ||
} | ||
|
||
if (valueToCheck) { | ||
const isValid = /^(manage|create|update|delete|read)/.test(valueToCheck); | ||
const usesValidSeparator = /^[a-z0-9_]+$/.test(valueToCheck); | ||
let method = 'manage'; | ||
|
||
if (valueToCheck.includes('read')) { | ||
method = 'read'; | ||
} | ||
|
||
if (valueToCheck.includes('create') || valueToCheck.includes('copy')) { | ||
method = 'create'; | ||
} | ||
|
||
if (valueToCheck.includes('delete')) { | ||
method = 'delete'; | ||
} | ||
|
||
if (valueToCheck.includes('update')) { | ||
method = 'update'; | ||
} | ||
|
||
if (!isValid) { | ||
return context.report({ | ||
node: element, | ||
message: `API privilege '${valueToCheck}' should start with [manage|create|update|delete|read] or use ApiPrivileges.${method} instead`, | ||
}); | ||
} | ||
|
||
if (!usesValidSeparator) { | ||
return context.report({ | ||
node: element, | ||
message: `API privilege '${valueToCheck}' should use '_' as a separator`, | ||
}); | ||
} | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
module.exports = { | ||
meta: { | ||
type: 'problem', | ||
docs: { | ||
description: 'Ensure API privileges in registerKibanaFeature call follow naming conventions', | ||
category: 'Best Practices', | ||
recommended: true, | ||
}, | ||
schema: [], | ||
}, | ||
|
||
create(context) { | ||
return { | ||
CallExpression(node) { | ||
const isRegisterKibanaFeatureCall = | ||
node.callee.type === 'MemberExpression' && | ||
node.callee.property.name === 'registerKibanaFeature' && | ||
((node.callee.object.type === 'MemberExpression' && | ||
node.callee.object.property.name === 'features') || | ||
node.callee.object.name === 'features'); | ||
|
||
if (!isRegisterKibanaFeatureCall) return; | ||
|
||
const scopedVariables = new Map(); | ||
|
||
const sourceCode = context.getSourceCode(); | ||
|
||
const parent = sourceCode | ||
.getAncestors(node) | ||
.find((ancestor) => ['BlockStatement', 'Program'].includes(ancestor.type)); | ||
|
||
if (parent) { | ||
parent.body.forEach((statement) => { | ||
if (statement.type === 'VariableDeclaration') { | ||
statement.declarations.forEach((declaration) => { | ||
if ( | ||
declaration.id.type === 'Identifier' && | ||
declaration.init && | ||
declaration.init.type === 'Literal' && | ||
typeof declaration.init.value === 'string' | ||
) { | ||
scopedVariables.set(declaration.id.name, declaration.init.value); | ||
} | ||
}); | ||
} | ||
}); | ||
} | ||
|
||
const [feature] = node.arguments; | ||
if (feature?.type === 'ObjectExpression') { | ||
const privilegesProperty = feature.properties.find( | ||
(prop) => | ||
prop.key && prop.key.name === 'privileges' && prop.value.type === 'ObjectExpression' | ||
); | ||
|
||
if (!privilegesProperty) return; | ||
|
||
return validatePrivilegesNode(context, privilegesProperty, scopedVariables); | ||
} | ||
}, | ||
ExportNamedDeclaration(node) { | ||
if ( | ||
node.declaration?.type !== 'VariableDeclaration' || | ||
!node.declaration.declarations?.length | ||
) { | ||
return; | ||
} | ||
|
||
node.declaration.declarations.forEach((declaration) => { | ||
if (declaration.init && declaration.init.type === 'ObjectExpression') { | ||
if ( | ||
!['id', 'name', 'privileges', 'scope', 'category'].every((key) => | ||
declaration.init.properties.find((prop) => prop.key?.name === key) | ||
) | ||
) { | ||
return; | ||
} | ||
|
||
const privilegesProperty = declaration.init.properties.find( | ||
(prop) => | ||
prop.key && prop.key.name === 'privileges' && prop.value.type === 'ObjectExpression' | ||
); | ||
|
||
validatePrivilegesNode(context, privilegesProperty, new Map()); | ||
} | ||
}); | ||
}, | ||
}; | ||
}, | ||
}; |
Oops, something went wrong.