Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Env variables to customize openapi filename #175

Merged
merged 2 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
9 changes: 6 additions & 3 deletions src/main/scala/io/appthreat/atom/Atom.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
Expand Down
19 changes: 12 additions & 7 deletions src/main/scala/io/appthreat/atom/slicing/ReachableSlicing.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down