diff --git a/README.md b/README.md index 96018e3..b91b70d 100644 --- a/README.md +++ b/README.md @@ -177,7 +177,11 @@ pip install atom-tools atom usages --extract-endpoints -o app.atom --slice-outfile usages.json -l java . ``` -A file called `openapi.generated.json` would be created with the endpoints information. +A file called `openapi.generated.json` would be created with the endpoints information. Use the environment variable `ATOM_TOOLS_OPENAPI_FILENAME` to customize the filename. + +```shell +ATOM_TOOLS_OPENAPI_FILENAME=openapi.json atom usages --extract-endpoints -o app.atom --slice-outfile usages.json -l ruby . +``` ### Export atom to graphml or dot format diff --git a/src/main/scala/io/appthreat/atom/Atom.scala b/src/main/scala/io/appthreat/atom/Atom.scala index e08c48f..32c56b8 100644 --- a/src/main/scala/io/appthreat/atom/Atom.scala +++ b/src/main/scala/io/appthreat/atom/Atom.scala @@ -363,14 +363,17 @@ object Atom: case u: UsagesConfig => saveSlice(config.outputSliceFile, sliceCpg(ag).map(_.toJson)) if u.extractEndpoints then + val openapiFileName = + sys.env.getOrElse("ATOM_TOOLS_OPENAPI_FILENAME", "openapi.generated.json") + val openapiFormat = sys.env.getOrElse("ATOM_TOOLS_OPENAPI_FORMAT", "openapi3.1.0") val result = ExternalCommand.run( - s"atom-tools convert -i ${config.outputSliceFile} -t ${config.language} -f openapi3.1.0 -q -o ${config - .inputPath.pathAsString}${java.io.File.separator}openapi.generated.json", + s"atom-tools convert -i ${config.outputSliceFile} -t ${config.language} -f ${openapiFormat} -q -o ${config + .inputPath.pathAsString}${java.io.File.separator}${openapiFileName}", "." ) result match case Success(_) => - println("openapi.generated.json created successfully.") + println(s"${openapiFileName} created successfully.") case Failure(exception) => println( s"Failed to run atom-tools. Use the atom container image or perform 'pip install atom-tools' and re-run this command. Exception: ${exception.getMessage}" diff --git a/src/main/scala/io/appthreat/atom/slicing/ReachableSlicing.scala b/src/main/scala/io/appthreat/atom/slicing/ReachableSlicing.scala index 0035d9a..13cc8bf 100644 --- a/src/main/scala/io/appthreat/atom/slicing/ReachableSlicing.scala +++ b/src/main/scala/io/appthreat/atom/slicing/ReachableSlicing.scala @@ -44,18 +44,23 @@ object ReachableSlicing: toSlice ).toList if config.includeCryptoFlows then - if language == Languages.JAVA || language == Languages.JAVASRC then + if Array(Languages.JAVA, Languages.JAVASRC).contains(language) then flowsList ++= atom.tag.name(CRYPTO_GENERATE_TAG).call.reachableByFlows( atom.tag.name(CRYPTO_ALGORITHM_TAG).literal ).map(toSlice).toList - else if language == Languages.PYTHON || language == Languages.PYTHONSRC then + else if Array(Languages.PYTHON, Languages.PYTHONSRC).contains(language) then flowsList ++= atom.tag.name(CRYPTO_GENERATE_TAG).call.reachableByFlows( atom.tag.name(CRYPTO_ALGORITHM_TAG).call ).map(toSlice).toList // For JavaScript and Python, we need flows between arguments of call nodes to track callbacks and middlewares if - language == Languages.JSSRC || language == Languages.JAVASCRIPT || language == Languages - .PYTHON || language == Languages.PYTHONSRC || language == Languages.RUBYSRC + Array( + Languages.JSSRC, + Languages.JAVASCRIPT, + Languages.PYTHON, + Languages.PYTHONSRC, + Languages.RUBYSRC + ).contains(language) then def dynCallSource = atom.tag.name(config.sourceTag).call.argument.isIdentifier def dynFrameworkIdentifier = atom.tag.name(FRAMEWORK_TAG).identifier @@ -80,7 +85,7 @@ object ReachableSlicing: .reachableByFlows(sourceI, dynFrameworkIdentifier) .map(toSlice) .toList - if language == Languages.PYTHON || language == Languages.PYTHONSRC then + if Array(Languages.PYTHON, Languages.PYTHONSRC).contains(language) then flowsList ++= atom.tag.name("pkg.*").identifier.reachableByFlows( atom.tag.name(CLI_SOURCE_TAG).identifier ).map(toSlice).toList @@ -89,7 +94,7 @@ object ReachableSlicing: atom.tag.name(CLI_SOURCE_TAG).call ).map(toSlice).toList end if - if language == Languages.PHP || language == Languages.RUBYSRC + if Array(Languages.PHP, Languages.RUBYSRC).contains(language) then flowsList ++= atom.ret.where(_.tag.name(config.sinkTag)).reachableByFlows( atom.tag.name(config.sourceTag).parameter @@ -113,7 +118,7 @@ object ReachableSlicing: _.maxDepth(config.sliceDepth) ).parameter ).map(toSlice).toList - if language == Languages.NEWC || language == Languages.C + if Array(Languages.NEWC, Languages.C).contains(language) then flowsList ++= atom.tag.name(LIBRARY_CALL_TAG).call.reachableByFlows(atom.tag.name( CLI_SOURCE_TAG