mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
python: create shared serverless module and use it
Modelled on the javascript serverless module, but - The predicate that reports YAML files is now public so languages can implement their own file conventions. - It also reports framework and runtime. - The conveninece predicates with files still exist, but they only report the path. - Handler mapping conventions are now documented. - Use parameterised serverless module in Python, tests now pass.
This commit is contained in:
@@ -49,6 +49,7 @@ private import semmle.python.frameworks.Requests
|
||||
private import semmle.python.frameworks.RestFramework
|
||||
private import semmle.python.frameworks.Rsa
|
||||
private import semmle.python.frameworks.RuamelYaml
|
||||
private import semmle.python.frameworks.ServerLess
|
||||
private import semmle.python.frameworks.Simplejson
|
||||
private import semmle.python.frameworks.SqlAlchemy
|
||||
private import semmle.python.frameworks.Starlette
|
||||
|
||||
59
python/ql/lib/semmle/python/frameworks/ServerLess.qll
Normal file
59
python/ql/lib/semmle/python/frameworks/ServerLess.qll
Normal file
@@ -0,0 +1,59 @@
|
||||
import python
|
||||
import codeql.serverless.ServerLess
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
import semmle.python.dataflow.new.RemoteFlowSources
|
||||
|
||||
private module YamlImpl implements Input {
|
||||
import semmle.python.Files
|
||||
import semmle.python.Yaml
|
||||
}
|
||||
|
||||
module SL = ServerLess<YamlImpl>;
|
||||
|
||||
/**
|
||||
* Gets a function that is a serverless request handler.
|
||||
*
|
||||
* For example: if an AWS serverless resource contains the following properties (in the "template.yml" file):
|
||||
* ```yaml
|
||||
* Handler: mylibrary.handler
|
||||
* Runtime: pythonXXX
|
||||
* CodeUri: backend/src/
|
||||
* ```
|
||||
*
|
||||
* And a file "mylibrary.py" exists in the folder "backend/src" (relative to the "template.yml" file).
|
||||
* Then the result of this predicate is a function exported as "handler" from "mylibrary.py".
|
||||
* The "mylibrary.py" file could for example look like:
|
||||
*
|
||||
* ```python
|
||||
* def handler(event):
|
||||
* ...
|
||||
* ```
|
||||
*/
|
||||
private Function getAServerlessHandler() {
|
||||
exists(File file, string stem, string handler, string runtime, Module mod |
|
||||
SL::hasServerlessHandler(stem, handler, _, runtime) and
|
||||
file.getAbsolutePath() = stem + ".py" and
|
||||
// if runtime is specified, it should be python
|
||||
(runtime = "" or runtime.matches("python%"))
|
||||
|
|
||||
mod.getFile() = file and
|
||||
mod.getAnExport() = handler and
|
||||
result.getEnclosingModule() = mod and
|
||||
result.getName() = handler
|
||||
)
|
||||
}
|
||||
|
||||
private DataFlow::ParameterNode getAHandlerEventParameter() {
|
||||
exists(Function func | func = getAServerlessHandler() |
|
||||
result.getParameter() in [func.getArg(0), func.getArgByName("event")]
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A serverless request handler event, seen as a RemoteFlowSource.
|
||||
*/
|
||||
private class ServerlessHandlerEventAsRemoteFlow extends RemoteFlowSource::Range {
|
||||
ServerlessHandlerEventAsRemoteFlow() { this = getAHandlerEventParameter() }
|
||||
|
||||
override string getSourceType() { result = "Serverless event" }
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
def handler1(event, context): # $ MISSING: remoteFlow=event, remoteFlow=context
|
||||
def handler1(event, context): # $ remoteFlow=event
|
||||
return "Hello World!"
|
||||
|
||||
def handler2(event, context): # $ MISSING: remoteFlow=event, remoteFlow=context
|
||||
def handler2(event, context): # $ remoteFlow=event
|
||||
return "Hello World!"
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
def lambda_handler(event, context): # $ MISSING: remoteFlow=event, remoteFlow=context
|
||||
def lambda_handler(event, context): # $ remoteFlow=event
|
||||
return "OK"
|
||||
|
||||
Reference in New Issue
Block a user