├── .github
└── workflows
│ ├── build.yml
│ └── release.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── build.gradle
├── config
└── checkstyle
│ └── checkstyle.xml
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── src
└── main
├── java
├── com
│ └── imperva
│ │ ├── apiattacktool
│ │ ├── ToolMain.java
│ │ ├── activators
│ │ │ ├── EndpointModelToValueConverter.java
│ │ │ ├── EndpointTestRequestDataConverter.java
│ │ │ ├── HttpRequestGenerator.java
│ │ │ ├── ModelToValueConverter.java
│ │ │ ├── RequestDataConverter.java
│ │ │ └── TestHttpRequestGenerator.java
│ │ ├── cli
│ │ │ ├── ApiAttackTool.java
│ │ │ └── TestListener.java
│ │ ├── fuzzing
│ │ │ ├── Fuzzer.java
│ │ │ ├── modelgenerators
│ │ │ │ ├── CloningIterativeFuzzedModelsGenerator.java
│ │ │ │ ├── FuzzedModelsGenerator.java
│ │ │ │ └── SingleValueFuzzedModelsGenerator.java
│ │ │ ├── parameters
│ │ │ │ ├── AllParametersPolicyEnforcer.java
│ │ │ │ ├── PolicyEnforcer.java
│ │ │ │ └── RequiredOnlyPolicyEnforcer.java
│ │ │ ├── path
│ │ │ │ └── PathFuzzer.java
│ │ │ └── value
│ │ │ │ ├── CommonValueFuzzer.java
│ │ │ │ ├── NegativeSingleValueFuzzer.java
│ │ │ │ ├── PositiveSingleValueFuzzer.java
│ │ │ │ └── ValueFuzzer.java
│ │ ├── infra
│ │ │ └── Tuple.java
│ │ ├── model
│ │ │ ├── tests
│ │ │ │ ├── BaseHttpResponseValidator.java
│ │ │ │ ├── EndpointTestRequestData.java
│ │ │ │ ├── HttpMethod.java
│ │ │ │ ├── HttpRequestWrapper.java
│ │ │ │ ├── HttpResponseValidator.java
│ │ │ │ ├── NegativeTestHttpResponseValidator.java
│ │ │ │ ├── ParameterLocation.java
│ │ │ │ └── PositiveTestHttpResponseValidator.java
│ │ │ └── valued
│ │ │ │ ├── ArrayPropertyValue.java
│ │ │ │ ├── ArrayPropertyValueAdapter.java
│ │ │ │ ├── BooleanPropertyValue.java
│ │ │ │ ├── EndpointValuedModel.java
│ │ │ │ ├── NumericPropertyValue.java
│ │ │ │ ├── PropertyPropertyValue.java
│ │ │ │ ├── PropertyValue.java
│ │ │ │ ├── PropertyValueNode.java
│ │ │ │ ├── StringPropertyValue.java
│ │ │ │ └── factory
│ │ │ │ ├── PropertyValueFactory.java
│ │ │ │ └── SimplePropertyValueFactory.java
│ │ ├── processors
│ │ │ ├── EndpointModelProcessor.java
│ │ │ └── FuzzEndpointModelProcessor.java
│ │ ├── tests
│ │ │ ├── AbstractTestDriver.java
│ │ │ ├── MainTest.java
│ │ │ ├── NegativeSinglePropertyScenarioTestDriver.java
│ │ │ ├── ScenariosDataProvider.java
│ │ │ ├── SingleValueScenarioTestDriver.java
│ │ │ ├── TestConfiguration.java
│ │ │ ├── TestDriver.java
│ │ │ └── TestHttpResponse.java
│ │ └── utils
│ │ │ └── TestReporter.java
│ │ └── apispecparser
│ │ ├── exceptions
│ │ └── ParseException.java
│ │ ├── model
│ │ ├── ArrayProperty.java
│ │ ├── BooleanProperty.java
│ │ ├── EndpointModel.java
│ │ ├── EnumerableProperty.java
│ │ ├── NumericProperty.java
│ │ ├── Property.java
│ │ ├── PropertyNode.java
│ │ ├── PropertyType.java
│ │ └── StringProperty.java
│ │ ├── normalizer
│ │ ├── ApiDefinitions.java
│ │ ├── NormalizedApiSpec.java
│ │ ├── NormalizedApiSpecImpl.java
│ │ ├── NormalizedEndpoint.java
│ │ ├── NormalizedEndpointImpl.java
│ │ ├── NormalizedParameter.java
│ │ ├── NormalizedPath.java
│ │ ├── NormalizedPathImpl.java
│ │ └── swagger
│ │ │ ├── SwaggerDefinitions.java
│ │ │ ├── SwaggerDefinitionsNormalizer.java
│ │ │ ├── SwaggerNormalizedApiSpec.java
│ │ │ ├── SwaggerNormalizedEndpoint.java
│ │ │ ├── SwaggerNormalizedParameter.java
│ │ │ └── SwaggerNormalizedPath.java
│ │ ├── parsers
│ │ ├── ApiSpecFileLocation.java
│ │ ├── ApiSpecParser.java
│ │ └── swagger
│ │ │ ├── Swagger2Parser.java
│ │ │ ├── property
│ │ │ ├── ApiKeyAuthenticationParamType.java
│ │ │ ├── ApiKeyAuthenticationProperties.java
│ │ │ ├── AuthenticationProperties.java
│ │ │ ├── SimpleSwaggerPropertyFactory.java
│ │ │ ├── SwaggerAuthenticationToPropertyFactory.java
│ │ │ ├── SwaggerParameterProperties.java
│ │ │ └── SwaggerPropertyFactory.java
│ │ │ └── propertynode
│ │ │ ├── SwaggerArrayItemsToPropertyNode.java
│ │ │ ├── SwaggerModelImplToPropertyNode.java
│ │ │ ├── SwaggerModelToPropertyNodeFactory.java
│ │ │ ├── SwaggerModelToPropertyNodeImpl.java
│ │ │ ├── SwaggerPropertyNodeConverter.java
│ │ │ └── SwaggerRefModelToPropertyNode.java
│ │ └── utils
│ │ └── FileUtils.java
└── testng.xml
└── resources
├── logback.xml
├── runnable.sh
└── swaggerPetStore.yaml
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build pipeline
2 |
3 | on: [push]
4 | jobs:
5 | build:
6 | runs-on: ubuntu-latest
7 | steps:
8 | - name: Checkout
9 | uses: actions/checkout@v1
10 | - name: Build
11 | run: ./gradlew clean build
12 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | # Creates a Github release and uploads it
2 | #
3 | # Prerequisite: create a secret called GITHUB_API_KEY with an Github token with public_repo scope
4 |
5 | name: Release pipeline
6 |
7 | on:
8 | push:
9 | tags:
10 | - 'v*' # Triggers only on tags like v1.0 (versions)
11 |
12 | jobs:
13 | build:
14 | name: Create a new release
15 | runs-on: ubuntu-latest
16 | steps:
17 | - name: Checkout code
18 | uses: actions/checkout@master
19 | - name: Get the version
20 | id: get_version
21 | run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3)
22 | - name: Build project
23 | run: |
24 | ./gradlew clean build
25 | - name: Create release
26 | id: create_release
27 | uses: actions/create-release@v1.0.0
28 | env:
29 | GITHUB_TOKEN: ${{ secrets.GITHUB_API_KEY }}
30 | with:
31 | tag_name: ${{ github.ref }}
32 | release_name: Release ${{ github.ref }}
33 | draft: false
34 | prerelease: false
35 | - name: Upload executable jar
36 | id: upload-release-asset
37 | uses: actions/upload-release-asset@v1.0.1
38 | env:
39 | GITHUB_TOKEN: ${{ secrets.GITHUB_API_KEY }}
40 | with:
41 | upload_url: ${{ steps.create_release.outputs.upload_url }}
42 | asset_path: ./build/libs/imperva-api-attack-tool.jar
43 | asset_name: imperva-api-attack-tool-${{ steps.get_version.outputs.VERSION }}.jar
44 | asset_content_type: application/zip
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/java,maven,macos,gradle,python,intellij+all
3 | # Edit at https://www.gitignore.io/?templates=java,maven,macos,gradle,python,intellij+all
4 |
5 | ### Intellij+all ###
6 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
7 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
8 |
9 | # User-specific stuff
10 | .idea/**/workspace.xml
11 | .idea/**/tasks.xml
12 | .idea/**/usage.statistics.xml
13 | .idea/**/dictionaries
14 | .idea/**/shelf
15 |
16 | # Generated files
17 | .idea/**/contentModel.xml
18 |
19 | # Sensitive or high-churn files
20 | .idea/**/dataSources/
21 | .idea/**/dataSources.ids
22 | .idea/**/dataSources.local.xml
23 | .idea/**/sqlDataSources.xml
24 | .idea/**/dynamic.xml
25 | .idea/**/uiDesigner.xml
26 | .idea/**/dbnavigator.xml
27 |
28 | # Gradle
29 | .idea/**/gradle.xml
30 | .idea/**/libraries
31 |
32 | # Gradle and Maven with auto-import
33 | # When using Gradle or Maven with auto-import, you should exclude module files,
34 | # since they will be recreated, and may cause churn. Uncomment if using
35 | # auto-import.
36 | # .idea/modules.xml
37 | # .idea/*.iml
38 | # .idea/modules
39 |
40 | # CMake
41 | cmake-build-*/
42 |
43 | # Mongo Explorer plugin
44 | .idea/**/mongoSettings.xml
45 |
46 | # File-based project format
47 | *.iws
48 |
49 | # IntelliJ
50 | out/
51 |
52 | # mpeltonen/sbt-idea plugin
53 | .idea_modules/
54 |
55 | # JIRA plugin
56 | atlassian-ide-plugin.xml
57 |
58 | # Cursive Clojure plugin
59 | .idea/replstate.xml
60 |
61 | # Crashlytics plugin (for Android Studio and IntelliJ)
62 | com_crashlytics_export_strings.xml
63 | crashlytics.properties
64 | crashlytics-build.properties
65 | fabric.properties
66 |
67 | # Editor-based Rest Client
68 | .idea/httpRequests
69 |
70 | # Android studio 3.1+ serialized cache file
71 | .idea/caches/build_file_checksums.ser
72 |
73 | ### Intellij+all Patch ###
74 | # Ignores the whole .idea folder and all .iml files
75 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
76 |
77 | .idea/
78 |
79 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
80 |
81 | *.iml
82 | modules.xml
83 | .idea/misc.xml
84 | *.ipr
85 |
86 | ### Java ###
87 | # Compiled class file
88 | *.class
89 |
90 | # Log file
91 | *.log
92 |
93 | # BlueJ files
94 | *.ctxt
95 |
96 | # Mobile Tools for Java (J2ME)
97 | .mtj.tmp/
98 |
99 | # Package Files #
100 | *.jar
101 | *.war
102 | *.nar
103 | *.ear
104 | *.zip
105 | *.tar.gz
106 | *.rar
107 |
108 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
109 | hs_err_pid*
110 |
111 | ### macOS ###
112 | # General
113 | .DS_Store
114 | .AppleDouble
115 | .LSOverride
116 |
117 | # Icon must end with two \r
118 | Icon
119 |
120 | # Thumbnails
121 | ._*
122 |
123 | # Files that might appear in the root of a volume
124 | .DocumentRevisions-V100
125 | .fseventsd
126 | .Spotlight-V100
127 | .TemporaryItems
128 | .Trashes
129 | .VolumeIcon.icns
130 | .com.apple.timemachine.donotpresent
131 |
132 | # Directories potentially created on remote AFP share
133 | .AppleDB
134 | .AppleDesktop
135 | Network Trash Folder
136 | Temporary Items
137 | .apdisk
138 |
139 | ### Maven ###
140 | target/
141 | pom.xml.tag
142 | pom.xml.releaseBackup
143 | pom.xml.versionsBackup
144 | pom.xml.next
145 | release.properties
146 | dependency-reduced-pom.xml
147 | buildNumber.properties
148 | .mvn/timing.properties
149 | .mvn/wrapper/maven-wrapper.jar
150 |
151 | ### Python ###
152 | # Byte-compiled / optimized / DLL files
153 | __pycache__/
154 | *.py[cod]
155 | *$py.class
156 |
157 | # C extensions
158 | *.so
159 |
160 | # Distribution / packaging
161 | .Python
162 | build/
163 | develop-eggs/
164 | dist/
165 | downloads/
166 | eggs/
167 | .eggs/
168 | lib/
169 | lib64/
170 | parts/
171 | sdist/
172 | var/
173 | wheels/
174 | share/python-wheels/
175 | *.egg-info/
176 | .installed.cfg
177 | *.egg
178 | MANIFEST
179 |
180 | # PyInstaller
181 | # Usually these files are written by a python script from a template
182 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
183 | *.manifest
184 | *.spec
185 |
186 | # Installer logs
187 | pip-log.txt
188 | pip-delete-this-directory.txt
189 |
190 | # Unit test / coverage reports
191 | htmlcov/
192 | .tox/
193 | .nox/
194 | .coverage
195 | .coverage.*
196 | .cache
197 | nosetests.xml
198 | coverage.xml
199 | *.cover
200 | .hypothesis/
201 | .pytest_cache/
202 |
203 | # Translations
204 | *.mo
205 | *.pot
206 |
207 | # Django stuff:
208 | local_settings.py
209 | db.sqlite3
210 |
211 | # Flask stuff:
212 | instance/
213 | .webassets-cache
214 |
215 | # Scrapy stuff:
216 | .scrapy
217 |
218 | # Sphinx documentation
219 | docs/_build/
220 |
221 | # PyBuilder
222 |
223 | # Jupyter Notebook
224 | .ipynb_checkpoints
225 |
226 | # IPython
227 | profile_default/
228 | ipython_config.py
229 |
230 | # pyenv
231 | .python-version
232 |
233 | # celery beat schedule file
234 | celerybeat-schedule
235 |
236 | # SageMath parsed files
237 | *.sage.py
238 |
239 | # Environments
240 | .env
241 | .venv
242 | env/
243 | venv/
244 | ENV/
245 | env.bak/
246 | venv.bak/
247 |
248 | # Spyder project settings
249 | .spyderproject
250 | .spyproject
251 |
252 | # Rope project settings
253 | .ropeproject
254 |
255 | # mkdocs documentation
256 | /site
257 |
258 | # mypy
259 | .mypy_cache/
260 | .dmypy.json
261 | dmypy.json
262 |
263 | # Pyre type checker
264 | .pyre/
265 |
266 | ### Python Patch ###
267 | .venv/
268 |
269 | ### Gradle ###
270 | .gradle
271 | /build/
272 |
273 | # Ignore Gradle GUI config
274 | gradle-app.setting
275 |
276 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
277 | !gradle-wrapper.jar
278 |
279 | # Cache of project
280 | .gradletasknamecache
281 |
282 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
283 | # gradle/wrapper/gradle-wrapper.properties
284 |
285 | ### Gradle Patch ###
286 | **/build/
287 |
288 | # End of https://www.gitignore.io/api/java,maven,macos,gradle,python,intellij+all
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imperva/automatic-api-attack-tool/2e039f2babd62f3cdbb522451b6fea0567396a99/CODE_OF_CONDUCT.md
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imperva/automatic-api-attack-tool/2e039f2babd62f3cdbb522451b6fea0567396a99/CONTRIBUTING.md
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 |
2 | MIT License
3 |
4 | Copyright (c) 2018 Imperva
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
7 |
8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 |
10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id "com.github.spotbugs" version "3.0.0"
3 | id 'application'
4 | }
5 |
6 | apply plugin: 'com.github.spotbugs'
7 | apply plugin: 'checkstyle'
8 |
9 | sourceCompatibility = 1.8
10 | project.ext.artifactId = "imperva-api-attack-tool"
11 | project.ext.version = '1.0'
12 | project.ext.buildNumber = System.getenv('BUILD_NUMBER') != null ? System.getenv('BUILD_NUMBER') : 0
13 |
14 | repositories {
15 | jcenter()
16 | mavenCentral()
17 | maven { url "https://dl.bintray.com/epam/reportportal" }
18 | }
19 |
20 | sourceSets {
21 | main {
22 | resources {
23 | srcDirs = ["src/main/resources"]
24 | exclude "**/*.java"
25 | }
26 | }
27 | test {
28 | resources {
29 | srcDirs = ["src/test/java", "src/test/resources"]
30 | exclude "**/*.java"
31 | }
32 | }
33 | }
34 |
35 | dependencies {
36 | implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.10.1'
37 | // Apache License 2.0
38 | implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.6' // Apache License 2.0
39 | implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.3' // LGPL v2.1
40 | implementation group: 'io.swagger.parser.v3', name: 'swagger-parser', version: '2.0.16' // Apache License 2.0
41 | implementation group: 'info.picocli', name: 'picocli', version: '4.1.0' // Apache License 2.0
42 | implementation group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.10' // Apache License 2.0
43 | implementation group: 'org.apache.httpcomponents', name: 'httpmime', version: '4.5.10' // Apache License 2.0
44 | implementation group: 'org.testng', name: 'testng', version: '7.0.0' // Apache License 2.0
45 | implementation group: 'org.slf4j', name: 'jcl-over-slf4j', version: '1.7.29'
46 | // MIT License (compatible with Apache License)
47 | implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.29'
48 | // MIT License (compatible with Apache License)
49 | }
50 |
51 | configurations {
52 | compile.exclude module: 'commons-logging'
53 | }
54 |
55 | jar {
56 | duplicatesStrategy = DuplicatesStrategy.INCLUDE
57 | archiveBaseName = project.ext.artifactId
58 | manifest {
59 | mainClassName = 'com.imperva.apiattacktool.ToolMain'
60 | attributes 'Implementation-Title': project.ext.artifactId,
61 | 'Implementation-Version': project.ext.version,
62 | 'Build-Number': project.ext.buildNumber,
63 | 'Main-Class': 'com.imperva.apiattacktool.ToolMain'
64 | }
65 | from {
66 | configurations.compileClasspath.collect {
67 | it.isDirectory() ? it : zipTree(it).matching { exclude { it.path.contains('META-INF') } }
68 | }
69 | }
70 | }
71 |
72 |
73 | spotbugsMain.enabled = false
74 | checkstyleMain.enabled = false
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/config/checkstyle/checkstyle.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
73 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
98 |
99 |
100 |
102 |
103 |
104 |
105 |
107 |
108 |
109 |
110 |
112 |
113 |
114 |
115 |
116 |
117 |
119 |
120 |
121 |
122 |
124 |
125 |
126 |
127 |
129 |
130 |
131 |
132 |
134 |
136 |
138 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imperva/automatic-api-attack-tool/2e039f2babd62f3cdbb522451b6fea0567396a99/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 30 16:31:57 CET 2019
2 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip
3 | distributionBase=GRADLE_USER_HOME
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn ( ) {
37 | echo "$*"
38 | }
39 |
40 | die ( ) {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save ( ) {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/ToolMain.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool;
2 |
3 | import ch.qos.logback.classic.LoggerContext;
4 | import ch.qos.logback.classic.joran.JoranConfigurator;
5 | import ch.qos.logback.core.joran.spi.JoranException;
6 | import com.imperva.apiattacktool.cli.ApiAttackTool;
7 | import org.slf4j.LoggerFactory;
8 | import picocli.CommandLine;
9 |
10 | import java.net.URL;
11 |
12 |
13 | public class ToolMain {
14 | public static void main(String[] args) {
15 | configureLogging();
16 | ApiAttackTool apiAttackTool = new ApiAttackTool();
17 | System.exit(new CommandLine(apiAttackTool).execute(args));
18 | }
19 |
20 | private static void configureLogging() {
21 | final LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
22 | try {
23 | JoranConfigurator configurator = new JoranConfigurator();
24 | configurator.setContext( context );
25 | context.reset();
26 | URL path = ClassLoader.getSystemClassLoader().getResource("logback.xml");
27 | configurator.doConfigure(path);
28 | }
29 | catch ( JoranException ignore ) {
30 | System.out.println("Logging is disabled");
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/activators/EndpointModelToValueConverter.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.activators;
2 |
3 | import com.imperva.apiattacktool.model.valued.EndpointValuedModel;
4 | import com.imperva.apiattacktool.model.valued.factory.PropertyValueFactory;
5 | import com.imperva.apispecparser.model.EndpointModel;
6 |
7 | import java.util.Collections;
8 | import java.util.List;
9 | import java.util.stream.Collectors;
10 |
11 | public class EndpointModelToValueConverter implements ModelToValueConverter {
12 |
13 | private PropertyValueFactory propertyValueFactory;
14 |
15 | public EndpointModelToValueConverter(PropertyValueFactory propertyValueFactory) {
16 | this.propertyValueFactory = propertyValueFactory;
17 | }
18 |
19 | @Override
20 | public List endpointModelToEndpointValuedModel(List endpointModelList) {
21 | List endpointValuedModelList = Collections.EMPTY_LIST;
22 | if (endpointModelList != null) {
23 | endpointValuedModelList = endpointModelList.stream().map(
24 | endpointModel -> new EndpointValuedModel(endpointModel, propertyValueFactory))
25 | .collect(Collectors.toList());
26 | }
27 | return endpointValuedModelList;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/activators/EndpointTestRequestDataConverter.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.activators;
2 |
3 | import com.google.gson.Gson;
4 | import com.imperva.apiattacktool.model.tests.EndpointTestRequestData;
5 | import com.imperva.apiattacktool.model.tests.ParameterLocation;
6 | import com.imperva.apiattacktool.model.valued.ArrayPropertyValue;
7 | import com.imperva.apiattacktool.model.valued.ArrayPropertyValueAdapter;
8 | import com.imperva.apiattacktool.model.valued.EndpointValuedModel;
9 | import com.imperva.apiattacktool.model.valued.PropertyValue;
10 | import com.imperva.apiattacktool.model.valued.PropertyValueNode;
11 |
12 | import java.util.Collections;
13 | import java.util.List;
14 | import java.util.Map;
15 | import java.util.Optional;
16 | import java.util.regex.Matcher;
17 | import java.util.stream.Collectors;
18 |
19 | public class EndpointTestRequestDataConverter implements RequestDataConverter {
20 |
21 | private final Gson gson;
22 |
23 | public EndpointTestRequestDataConverter() {
24 | gson = new Gson();
25 | }
26 |
27 | @Override
28 | public List processList(List endpointModelList) {
29 | if (endpointModelList == null) {
30 | return Collections.emptyList();
31 | }
32 |
33 | List endpointTestRequestDataList = endpointModelList.stream()
34 | .map(this::convertFrom)
35 | .collect(Collectors.toList());
36 | return endpointTestRequestDataList;
37 | }
38 |
39 | private EndpointTestRequestData convertFrom(EndpointValuedModel endpointValuedModel) {
40 | Map> parameterLocationToPropertyValueMap =
41 | endpointValuedModel.getPropertiesMap().values().stream()
42 | .filter(propertyValue -> propertyValue.getParameterLocation() != ParameterLocation.BODY)
43 | .map(propertyValue -> propertyValue instanceof ArrayPropertyValue ? new ArrayPropertyValueAdapter((ArrayPropertyValue) propertyValue) :
44 | propertyValue)
45 | .collect(Collectors.groupingBy(PropertyValue::getParameterLocation));
46 |
47 | Optional> bodyParamEntry =
48 | endpointValuedModel.getChildrenMap().entrySet().stream()
49 | .filter(stringPropertyValueNodeEntry -> stringPropertyValueNodeEntry.getValue().getParameterLocation() == ParameterLocation.BODY)
50 | .findFirst();
51 |
52 | String bodyParamString = null;
53 | if (bodyParamEntry.isPresent()) {
54 | Map bodyParamMapRepresentation = bodyParamEntry.get().getValue().bodyParameterJsonRepresentationMap();
55 | bodyParamString = gson.toJson(bodyParamMapRepresentation);
56 | }
57 |
58 | String urlWithInjectedValues =
59 | getUrlInjectedWithValues(endpointValuedModel.getFullPathWithParamBrackets(), parameterLocationToPropertyValueMap.get(ParameterLocation.PATH));
60 | EndpointTestRequestData endpointTestRequestData =
61 | new EndpointTestRequestData(endpointValuedModel.getHttpMethod(), endpointValuedModel.getFullPathWithParamBrackets(), urlWithInjectedValues,
62 | parameterLocationToPropertyValueMap, bodyParamString, endpointValuedModel.getConsumes(), endpointValuedModel.getTestComment(),
63 | endpointValuedModel.getHttpResponseCodesCollection());
64 | return endpointTestRequestData;
65 | }
66 |
67 | private String getUrlInjectedWithValues(String urlWithPathParametersInBrackets, List pathParametersList) {
68 | if (pathParametersList == null) {
69 | return urlWithPathParametersInBrackets;
70 | }
71 |
72 | String injectedString = urlWithPathParametersInBrackets;
73 | for (PropertyValue propertyValue : pathParametersList) {
74 | injectedString = injectedString.replaceAll(
75 | getPathParameterPatternToReplace(propertyValue.getName()), Matcher.quoteReplacement(String.valueOf(propertyValue.getValue())));
76 | }
77 | return injectedString;
78 | }
79 |
80 | /**
81 | * @param pathParamName Path parameter name
82 | * @return Path parameter pattern
83 | */
84 | private String getPathParameterPatternToReplace(String pathParamName) {
85 | return "\\{" + pathParamName + "}";
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/activators/HttpRequestGenerator.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.activators;
2 |
3 | import com.imperva.apiattacktool.model.tests.EndpointTestRequestData;
4 | import com.imperva.apiattacktool.model.tests.HttpRequestWrapper;
5 |
6 | import java.util.List;
7 |
8 | public interface HttpRequestGenerator {
9 | List generateFrom(List endpointTestRequestDataList);
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/activators/ModelToValueConverter.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.activators;
2 |
3 | import com.imperva.apiattacktool.model.valued.EndpointValuedModel;
4 | import com.imperva.apispecparser.model.EndpointModel;
5 |
6 | import java.util.List;
7 |
8 | public interface ModelToValueConverter {
9 |
10 | List endpointModelToEndpointValuedModel(List endpointModelList);
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/activators/RequestDataConverter.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.activators;
2 |
3 | import com.imperva.apiattacktool.model.tests.EndpointTestRequestData;
4 | import com.imperva.apiattacktool.model.valued.EndpointValuedModel;
5 |
6 | import java.util.List;
7 |
8 | public interface RequestDataConverter {
9 | List processList(List endpointModelList);
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/activators/TestHttpRequestGenerator.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.activators;
2 |
3 | import com.imperva.apiattacktool.model.tests.EndpointTestRequestData;
4 | import com.imperva.apiattacktool.model.tests.HttpMethod;
5 | import com.imperva.apiattacktool.model.tests.HttpRequestWrapper;
6 | import com.imperva.apiattacktool.model.tests.HttpResponseValidator;
7 | import com.imperva.apiattacktool.model.valued.PropertyValue;
8 | import org.apache.http.HttpRequest;
9 | import org.apache.http.MethodNotSupportedException;
10 | import org.apache.http.client.utils.URIBuilder;
11 | import org.apache.http.entity.ContentType;
12 | import org.apache.http.entity.StringEntity;
13 | import org.apache.http.entity.mime.MultipartEntityBuilder;
14 | import org.apache.http.entity.mime.content.ContentBody;
15 | import org.apache.http.entity.mime.content.StringBody;
16 | import org.apache.http.impl.DefaultHttpRequestFactory;
17 | import org.apache.http.message.BasicHeader;
18 | import org.apache.http.message.BasicHttpEntityEnclosingRequest;
19 | import org.apache.http.protocol.HTTP;
20 | import org.slf4j.Logger;
21 | import org.slf4j.LoggerFactory;
22 |
23 | import java.net.URISyntaxException;
24 | import java.util.Collection;
25 | import java.util.Collections;
26 | import java.util.List;
27 | import java.util.Objects;
28 | import java.util.function.Function;
29 | import java.util.stream.Collectors;
30 |
31 | public class TestHttpRequestGenerator implements HttpRequestGenerator {
32 |
33 | private static final Logger logger = LoggerFactory.getLogger(TestHttpRequestGenerator.class);
34 | private Function, HttpResponseValidator> httpResponseValidatorGenerator;
35 |
36 | public TestHttpRequestGenerator(Function, HttpResponseValidator> httpResponseValidatorGenerator) {
37 | this.httpResponseValidatorGenerator = httpResponseValidatorGenerator;
38 | }
39 |
40 | @Override
41 | public List generateFrom(List endpointTestRequestDataList) {
42 | if (endpointTestRequestDataList == null) {
43 | return Collections.emptyList();
44 | }
45 | List httpRequestList =
46 | endpointTestRequestDataList.stream()
47 | .map(endpointTestRequestData -> {
48 | try {
49 | return generateFrom(endpointTestRequestData);
50 | } catch (MethodNotSupportedException methodNotSupportedException) {
51 | logger.error("Could not create create HttpRequest for this endpoint: {}", endpointTestRequestData, methodNotSupportedException);
52 | return null; // swallow and continue
53 | }
54 | })
55 | .filter(Objects::nonNull)
56 | .collect(Collectors.toList());
57 | return httpRequestList;
58 | }
59 |
60 | private HttpRequestWrapper generateFrom(EndpointTestRequestData endpointTestRequestData) throws MethodNotSupportedException {
61 | HttpRequest httpRequest;
62 | HttpMethod httpMethod = endpointTestRequestData.getHttpMethod();
63 | try {
64 | String url = endpointTestRequestData.getEndpointUrl();
65 | if (endpointTestRequestData.hasQueryParameters()) {
66 | url = attachQueryParametersToUrl(endpointTestRequestData.getEndpointUrl(), endpointTestRequestData.getQueryParameters());
67 | }
68 |
69 | if (endpointTestRequestData.getHttpMethod() != HttpMethod.PATCH) {
70 | httpRequest = DefaultHttpRequestFactory.INSTANCE.newHttpRequest(httpMethod.toString(), url);
71 | } else {
72 | httpRequest = new BasicHttpEntityEnclosingRequest(httpMethod.toString(), url);
73 | }
74 | if (endpointTestRequestData.hasHeaderParameters()) {
75 | updateRequestWithRequestHeaders(httpRequest, endpointTestRequestData.getHeaderParameters());
76 | }
77 | } catch (URISyntaxException uriSyntaxException) {
78 | logger.error("Couldn't generate http request for {}", endpointTestRequestData, uriSyntaxException);
79 | return null;
80 | }
81 |
82 | if (httpRequest instanceof BasicHttpEntityEnclosingRequest) {
83 | BasicHttpEntityEnclosingRequest basicHttpEntityEnclosingRequest = (BasicHttpEntityEnclosingRequest) httpRequest;
84 | if (endpointTestRequestData.hasBodyParameters()) {
85 | String bodyString = endpointTestRequestData.getBodyParameter();
86 | logger.debug("Endpoint: {} [{}], Body: {}", endpointTestRequestData.getEndpointUrl(), httpMethod, bodyString);
87 | if (bodyString != null) {
88 | try {
89 | StringEntity entity = new StringEntity(endpointTestRequestData.getBodyParameter(), "UTF-8");
90 | basicHttpEntityEnclosingRequest.setEntity(entity);
91 | } catch (Exception anyException) {
92 | logger.error("Encountered an error while setting body string for endpoint url: {}, method: {}",
93 | endpointTestRequestData.getEndpointUrl(), endpointTestRequestData.getHttpMethod(), anyException);
94 | }
95 | }
96 | } else if (endpointTestRequestData.hasFormDataParameters()) {
97 | MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
98 | endpointTestRequestData.getFormDataParameters().forEach(propertyValue ->
99 | multipartEntityBuilder.addPart(propertyValue.getName(), formDataToContentBody(propertyValue,
100 | endpointTestRequestData.getConsumesMimeTypes())));
101 | basicHttpEntityEnclosingRequest.setEntity(multipartEntityBuilder.build());
102 | }
103 | }
104 |
105 | HttpRequestWrapper httpRequestWrapper = new HttpRequestWrapper(httpRequest, endpointTestRequestData.getTestComment(),
106 | httpResponseValidatorGenerator.apply(endpointTestRequestData.getHttpResponseCodesCollection()));
107 | return httpRequestWrapper;
108 | }
109 |
110 | private ContentBody formDataToContentBody(PropertyValue formDataPropertyValue, List consumesMimeTypes) {
111 | String mimeTypeString = (consumesMimeTypes == null || consumesMimeTypes.isEmpty())
112 | ? ContentType.APPLICATION_FORM_URLENCODED.getMimeType()
113 | : consumesMimeTypes.get(0);
114 |
115 | switch (formDataPropertyValue.getType()) {
116 | case FILE:
117 | case BYTE_ARRAY:
118 | // not implemented right now, but should use ByteArrayBody
119 | case ARRAY:
120 | case FLOAT:
121 | case LONG:
122 | case DECIMAL:
123 | case DOUBLE:
124 | case BASE_INTEGER:
125 | case INTEGER:
126 | case UUID:
127 | case PASSWORD:
128 | case EMAIL:
129 | case DATETIME:
130 | case DATE:
131 | case BINARY:
132 | case STRING:
133 | case BOOLEAN:
134 | return new StringBody(String.valueOf(formDataPropertyValue.getValue()), ContentType.getByMimeType(mimeTypeString));
135 | case UNTYPED:
136 | default:
137 | return new StringBody(String.valueOf(formDataPropertyValue.getValue()), ContentType.TEXT_PLAIN);
138 | }
139 | }
140 |
141 | private void updateRequestWithRequestHeaders(HttpRequest httpRequest, List headerParameters) {
142 | headerParameters.forEach(propertyValue -> httpRequest.addHeader(propertyValue.getName(), String.valueOf(propertyValue.getValue())));
143 | }
144 |
145 | private String attachQueryParametersToUrl(String url, List queryParameters) throws URISyntaxException {
146 | URIBuilder builder = new URIBuilder(url);
147 | queryParameters.forEach(queryParam -> builder.addParameter(queryParam.getName(), String.valueOf(queryParam.getValue())));
148 | return builder.build().toString();
149 | }
150 |
151 | // Add cookie handling
152 | }
153 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/cli/ApiAttackTool.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.cli;
2 |
3 | import com.imperva.apiattacktool.tests.TestConfiguration;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 | import org.testng.TestNG;
7 | import picocli.CommandLine.Command;
8 | import picocli.CommandLine.Option;
9 |
10 | import java.util.List;
11 | import java.util.concurrent.Callable;
12 |
13 | @Command(name = "api-attack", mixinStandardHelpOptions = true, requiredOptionMarker = '*')
14 | public class ApiAttackTool implements Callable {
15 |
16 | private static final Logger logger = LoggerFactory.getLogger(ApiAttackTool.class);
17 |
18 | @Option(names = {"-f", "--specFile"}, required = true, description = "The API specification file (Swagger 2.0) to run on. JSON/YAML format. For better results, make sure responses are well defined for each endpoint.")
19 | private String specFilePath;
20 |
21 | @Option(names = {"-s", "--hostScheme"}, required = true, description = "Connection to host will be made using this scheme; e.g: https or http")
22 | private String hostScheme;
23 |
24 | @Option(names = {"-n", "--hostName"}, required = true, description = "The host name to connect to. It can also be an IP")
25 | private String hostName;
26 |
27 | @Option(names = {"-p", "--hostPort"}, description = "The port the host is listening on for API calls")
28 | private Integer hostPort;
29 |
30 | @Option(names = {"-ph", "--proxyHost"}, description = "Specify the proxy host to send the requests via a proxy")
31 | private String proxyHost;
32 |
33 | @Option(names = {"-pp", "--proxyPort"}, description = "The proxy port")
34 | private Integer proxyPort;
35 |
36 | @Option(names = {"-rcp", "--addPositiveRC"}, split = ",", description = "Additional response codes to be accepted in positive checks (legitimate value attacks). Multiple values are supported, separated by commas")
37 | private List userProvidedPositiveResponseCodes;
38 |
39 | @Option(names = {"-rcn", "--addNegativeRC"}, split = ",", description = "Additional response codes to be accepted in negative attacks (e.g. bad value attacks). Multiple values are supported, separated by commas")
40 | private List userProvidedNegativeResponseCodes;
41 |
42 | public String getSpecFilePath() {
43 | return specFilePath;
44 | }
45 |
46 | public String getHostScheme() {
47 | return hostScheme;
48 | }
49 |
50 | public String getHostName() {
51 | return hostName;
52 | }
53 |
54 | public Integer getHostPort() {
55 | return hostPort;
56 | }
57 |
58 | public String getProxyHost() {
59 | return proxyHost;
60 | }
61 |
62 | public Integer getProxyPort() {
63 | return proxyPort;
64 | }
65 |
66 | public List getUserProvidedPositiveResponseCodes() {
67 | return userProvidedPositiveResponseCodes;
68 | }
69 |
70 | public List getUserProvidedNegativeResponseCodes() {
71 | return userProvidedNegativeResponseCodes;
72 | }
73 |
74 | @Override
75 | public Integer call() {
76 | TestConfiguration.initFrom(this);
77 | logger.info("Running with this configuration:\n{}", TestConfiguration.getWorkingConfigurationString());
78 |
79 | TestNG testNG = new TestNG();
80 | testNG.setOutputDirectory("build/testng-results");
81 | testNG.addListener(new TestListener());
82 | testNG.setTestClasses(new Class[] {
83 | com.imperva.apiattacktool.tests.MainTest.class});
84 | testNG.setDefaultSuiteName("API Attacks");
85 | testNG.setDefaultTestName("Full Suite");
86 | testNG.setVerbose(1);
87 | testNG.run();
88 |
89 | return testNG.getStatus();
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/cli/TestListener.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.cli;
2 |
3 | import org.testng.ISuite;
4 | import org.testng.ISuiteListener;
5 |
6 | public class TestListener implements ISuiteListener {
7 |
8 | @Override
9 | public void onFinish(ISuite suite) {
10 | System.out.println("Tool run results output directory = " + suite.getOutputDirectory());
11 | }
12 |
13 | }
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/fuzzing/Fuzzer.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.fuzzing;
2 |
3 | import com.imperva.apiattacktool.model.valued.PropertyValueNode;
4 | import com.imperva.apispecparser.model.ArrayProperty;
5 | import com.imperva.apispecparser.model.BooleanProperty;
6 | import com.imperva.apispecparser.model.NumericProperty;
7 | import com.imperva.apispecparser.model.Property;
8 | import com.imperva.apispecparser.model.StringProperty;
9 |
10 | import java.util.List;
11 |
12 | public interface Fuzzer {
13 | List fuzz(Property property);
14 |
15 | List fuzz(BooleanProperty booleanProperty);
16 |
17 | List fuzz(StringProperty stringProperty);
18 |
19 | List fuzz(NumericProperty numericProperty);
20 |
21 | List> fuzz(ArrayProperty arrayProperty);
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/fuzzing/modelgenerators/CloningIterativeFuzzedModelsGenerator.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.fuzzing.modelgenerators;
2 |
3 | import com.imperva.apiattacktool.fuzzing.Fuzzer;
4 | import com.imperva.apiattacktool.model.valued.EndpointValuedModel;
5 | import com.imperva.apiattacktool.model.valued.PropertyValue;
6 | import com.imperva.apiattacktool.model.valued.PropertyValueNode;
7 | import com.imperva.apiattacktool.model.valued.factory.PropertyValueFactory;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 |
11 | import java.io.UnsupportedEncodingException;
12 | import java.net.URLEncoder;
13 | import java.nio.charset.StandardCharsets;
14 | import java.util.Collections;
15 | import java.util.LinkedList;
16 | import java.util.List;
17 | import java.util.Map;
18 |
19 | public class CloningIterativeFuzzedModelsGenerator implements FuzzedModelsGenerator {
20 | private static final Logger logger = LoggerFactory.getLogger(CloningIterativeFuzzedModelsGenerator.class);
21 |
22 | private PropertyValueFactory propertyValueFactory;
23 |
24 | public CloningIterativeFuzzedModelsGenerator(PropertyValueFactory propertyValueFactory) {
25 | this.propertyValueFactory = propertyValueFactory;
26 | }
27 |
28 | /**
29 | * Requires an already fuzzed endpointValueModel, since assumes all other values in iteration are already set
30 | *
31 | * @param endpointValuedModel
32 | * @param fuzzer
33 | * @return
34 | */
35 | @Override
36 | public List fuzzModelValues(EndpointValuedModel endpointValuedModel, Fuzzer fuzzer) {
37 | if (endpointValuedModel == null) {
38 | return Collections.emptyList();
39 | }
40 |
41 | List fuzzedEndpointValuedModelList = fuzzModelValue(endpointValuedModel, fuzzer);
42 | return fuzzedEndpointValuedModelList;
43 | }
44 |
45 | @Override
46 | public PropertyValueFactory getPropertyValueFactory() {
47 | return propertyValueFactory;
48 | }
49 |
50 |
51 | private List fuzzModelValue(EndpointValuedModel endpointValuedModel, Fuzzer fuzzer) {
52 | EndpointValuedModel clonedEndpointValueModel;
53 | try {
54 | clonedEndpointValueModel = (EndpointValuedModel) endpointValuedModel.clone();
55 | } catch (CloneNotSupportedException cloneException) {
56 | logger.error("Clone of endpointValuedModel failed: {} {}",
57 | endpointValuedModel.getHttpMethod(), endpointValuedModel.getFullPathWithParamBrackets());
58 | clonedEndpointValueModel = endpointValuedModel;
59 | }
60 |
61 | List fuzzedEndpointModelValuesList =
62 | traverseFuzzAndInjectPropertyValueNode(clonedEndpointValueModel, clonedEndpointValueModel.getPropertyValueNode(), fuzzer, null);
63 | return fuzzedEndpointModelValuesList;
64 | }
65 |
66 | private List fuzzAndInjectPropertyValues(EndpointValuedModel referenceModel, Map nameToPropertyValueMap,
67 | Fuzzer fuzzer, String relativePathForPropertyName) {
68 | List resultList = new LinkedList<>();
69 |
70 | nameToPropertyValueMap.entrySet().forEach(
71 | stringToPropertyValueEntry -> {
72 | PropertyValue propertyValue = stringToPropertyValueEntry.getValue();
73 | List> valuesList = propertyValue.fuzz(fuzzer);
74 | if (valuesList != null && !valuesList.isEmpty()) {
75 | // Store current value
76 | Object currentValue = stringToPropertyValueEntry.getValue().getValue();
77 | // Set fuzzed value and clone
78 | stringToPropertyValueEntry.getValue().setValue(valuesList.get(0));
79 |
80 | EndpointValuedModel clonedReferenceModel;
81 | try {
82 | clonedReferenceModel = (EndpointValuedModel) referenceModel.clone();
83 | clonedReferenceModel.setTestComment(
84 | "Property: " + buildRelativePath(relativePathForPropertyName, stringToPropertyValueEntry.getKey())
85 | + " (" + stringToPropertyValueEntry.getValue().getType() + "), value: " + stringToPropertyValueEntry.getValue().getValue()
86 | + ", URL encoded: "
87 | + URLEncoder.encode(String.valueOf(stringToPropertyValueEntry.getValue().getValue()), StandardCharsets.UTF_8.toString()));
88 | resultList.add(clonedReferenceModel);
89 | } catch (CloneNotSupportedException | UnsupportedEncodingException e) {
90 | logger.error("Error cloning reference model: {}", referenceModel);
91 | return;
92 | }
93 | // Put current value back
94 | stringToPropertyValueEntry.getValue().setValue(currentValue);
95 | }
96 | });
97 | return resultList;
98 | }
99 |
100 | private List traverseFuzzAndInjectPropertyValueNode(EndpointValuedModel referenceModel, PropertyValueNode propertyValueNode,
101 | Fuzzer fuzzer, String relativePathForPropertyName) {
102 | List resultList = new LinkedList<>();
103 | if (relativePathForPropertyName == null) {
104 | relativePathForPropertyName = "";
105 | }
106 |
107 | if (propertyValueNode.getPropertiesMap().size() > 0) {
108 | resultList.addAll(fuzzAndInjectPropertyValues(referenceModel, propertyValueNode.getPropertiesMap(), fuzzer, relativePathForPropertyName));
109 | }
110 |
111 | if (propertyValueNode.getChildrenMap().size() > 0) {
112 | for (Map.Entry stringToPropertyNodeMap : propertyValueNode.getChildrenMap().entrySet()) {
113 | resultList.addAll(traverseFuzzAndInjectPropertyValueNode(referenceModel, stringToPropertyNodeMap.getValue(), fuzzer,
114 | buildRelativePath(relativePathForPropertyName, stringToPropertyNodeMap.getKey())));
115 | }
116 | }
117 | return resultList;
118 | }
119 |
120 | private String buildRelativePath(String parent, String son) {
121 | return parent + "/" + son;
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/fuzzing/modelgenerators/FuzzedModelsGenerator.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.fuzzing.modelgenerators;
2 |
3 | import com.imperva.apiattacktool.fuzzing.Fuzzer;
4 | import com.imperva.apiattacktool.model.valued.EndpointValuedModel;
5 | import com.imperva.apiattacktool.model.valued.factory.PropertyValueFactory;
6 |
7 | import java.util.List;
8 |
9 | public interface FuzzedModelsGenerator {
10 | List fuzzModelValues(EndpointValuedModel endpointValuedModel, Fuzzer fuzzer);
11 |
12 | PropertyValueFactory getPropertyValueFactory();
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/fuzzing/modelgenerators/SingleValueFuzzedModelsGenerator.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.fuzzing.modelgenerators;
2 |
3 | import com.imperva.apiattacktool.fuzzing.Fuzzer;
4 | import com.imperva.apiattacktool.model.valued.EndpointValuedModel;
5 | import com.imperva.apiattacktool.model.valued.PropertyValue;
6 | import com.imperva.apiattacktool.model.valued.PropertyValueNode;
7 | import com.imperva.apiattacktool.model.valued.factory.PropertyValueFactory;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 |
11 | import java.util.Collections;
12 | import java.util.LinkedList;
13 | import java.util.List;
14 | import java.util.Map;
15 | // TODO: Fuzzer should take MIME type (and it's corresponding charset) into account, when generating values for formData params
16 | public class SingleValueFuzzedModelsGenerator implements FuzzedModelsGenerator {
17 | private static final Logger logger = LoggerFactory.getLogger(SingleValueFuzzedModelsGenerator.class);
18 |
19 | private PropertyValueFactory propertyValueFactory;
20 |
21 | public SingleValueFuzzedModelsGenerator(PropertyValueFactory propertyValueFactory) {
22 | this.propertyValueFactory = propertyValueFactory;
23 | }
24 |
25 | @Override
26 | public List fuzzModelValues(EndpointValuedModel endpointValuedModel, Fuzzer fuzzer) {
27 | if (endpointValuedModel == null) {
28 | return Collections.emptyList();
29 | }
30 |
31 | List endpointValuedModelList = new LinkedList<>();
32 | endpointValuedModelList.add(fuzzModelValue(endpointValuedModel, fuzzer));
33 | return endpointValuedModelList;
34 | }
35 |
36 | @Override
37 | public PropertyValueFactory getPropertyValueFactory() {
38 | return propertyValueFactory;
39 | }
40 |
41 |
42 | private EndpointValuedModel fuzzModelValue(EndpointValuedModel endpointValuedModel, Fuzzer fuzzer) {
43 | EndpointValuedModel clonedEndpointValueModel;
44 | try {
45 | clonedEndpointValueModel = (EndpointValuedModel) endpointValuedModel.clone();
46 | } catch (CloneNotSupportedException cloneException) {
47 | logger.error("Clone of endpointValuedModel failed: {} {}",
48 | endpointValuedModel.getHttpMethod(), endpointValuedModel.getFullPathWithParamBrackets());
49 | clonedEndpointValueModel = endpointValuedModel;
50 | }
51 | clonedEndpointValueModel.setTestComment(endpointValuedModel.getFullPathWithParamBrackets());
52 | fuzzAndInjectPropertyValues(clonedEndpointValueModel.getPropertiesMap(), fuzzer);
53 | clonedEndpointValueModel.getChildrenMap().entrySet().forEach(
54 | nameToPropertyValueNodeEntry -> {
55 | traverseFuzzAndInjectPropertyValueNode(nameToPropertyValueNodeEntry.getValue(), fuzzer);
56 | });
57 | return clonedEndpointValueModel;
58 | }
59 |
60 | private void fuzzAndInjectPropertyValues(Map nameToPropertyValueMap, Fuzzer fuzzer) {
61 | List propertiesToDeleteList = new LinkedList<>();
62 | nameToPropertyValueMap.entrySet().forEach(
63 | stringToPropertyValueEntry -> {
64 | PropertyValue propertyValue = stringToPropertyValueEntry.getValue();
65 | List extends PropertyValue> valuesList = propertyValue.fuzz(fuzzer);
66 | if (valuesList != null && !valuesList.isEmpty()) {
67 | stringToPropertyValueEntry.getValue().setValue(valuesList.get(0));
68 | } else {
69 | propertiesToDeleteList.add(stringToPropertyValueEntry.getKey());
70 | }
71 | });
72 | propertiesToDeleteList.forEach(name -> nameToPropertyValueMap.remove(name));
73 | }
74 |
75 | private void traverseFuzzAndInjectPropertyValueNode(PropertyValueNode propertyValueNode, Fuzzer fuzzer) {
76 |
77 | if (propertyValueNode.getPropertiesMap().size() > 0) {
78 | fuzzAndInjectPropertyValues(propertyValueNode.getPropertiesMap(), fuzzer);
79 | }
80 |
81 | if (propertyValueNode.getChildrenMap().size() > 0) {
82 | propertyValueNode.getChildrenMap().entrySet().forEach(
83 | stringToPropertyNodeMap ->
84 | traverseFuzzAndInjectPropertyValueNode(stringToPropertyNodeMap.getValue(), fuzzer)
85 | );
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/fuzzing/parameters/AllParametersPolicyEnforcer.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.fuzzing.parameters;
2 |
3 | import com.imperva.apiattacktool.model.valued.EndpointValuedModel;
4 |
5 | import java.util.List;
6 |
7 | public class AllParametersPolicyEnforcer implements PolicyEnforcer {
8 | @Override
9 | public List enforcePolicyOn(List endpointValuedModelList) {
10 | return endpointValuedModelList; // NO-OP
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/fuzzing/parameters/PolicyEnforcer.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.fuzzing.parameters;
2 |
3 | import com.imperva.apiattacktool.model.valued.EndpointValuedModel;
4 |
5 | import java.util.List;
6 |
7 | public interface PolicyEnforcer {
8 | List enforcePolicyOn(List endpointValuedModelList);
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/fuzzing/parameters/RequiredOnlyPolicyEnforcer.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.fuzzing.parameters;
2 |
3 | import com.imperva.apiattacktool.model.valued.EndpointValuedModel;
4 | import com.imperva.apiattacktool.model.valued.PropertyValue;
5 | import com.imperva.apiattacktool.model.valued.PropertyValueNode;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import java.util.Collections;
10 | import java.util.List;
11 | import java.util.Map;
12 | import java.util.stream.Collectors;
13 |
14 | /**
15 | * Makes sure the supplied endpointValueModels only have required parameters and properties.
16 | */
17 | public class RequiredOnlyPolicyEnforcer implements PolicyEnforcer {
18 | private static final Logger logger = LoggerFactory.getLogger(RequiredOnlyPolicyEnforcer.class);
19 |
20 | @Override
21 | public List enforcePolicyOn(List endpointValuedModelList) {
22 | if (endpointValuedModelList == null) {
23 | return Collections.emptyList();
24 | }
25 |
26 | List processedEndpointValueModelList =
27 | endpointValuedModelList.stream()
28 | .map(endpointValuedModel -> processModel(endpointValuedModel))
29 | .collect(Collectors.toList());
30 | return processedEndpointValueModelList;
31 | }
32 |
33 | private EndpointValuedModel processModel(EndpointValuedModel endpointValuedModel) {
34 | EndpointValuedModel clonedEndpointValueModel;
35 | try {
36 | clonedEndpointValueModel = (EndpointValuedModel) endpointValuedModel.clone();
37 | } catch (CloneNotSupportedException cloneException) {
38 | logger.error("Clone of endpointValuedModel failed: {} {}",
39 | endpointValuedModel.getHttpMethod(), endpointValuedModel.getFullPathWithParamBrackets());
40 | clonedEndpointValueModel = endpointValuedModel;
41 | }
42 |
43 | PropertyValueNode processedPropertyValueNode = processPropertyValueNode(clonedEndpointValueModel.getPropertyValueNode());
44 | clonedEndpointValueModel.setPropertyValueNode(processedPropertyValueNode);
45 | return clonedEndpointValueModel;
46 | }
47 |
48 | private Map processPropertyValues(Map nameToPropertyValueMap) {
49 | Map processedPropertiesMap = nameToPropertyValueMap.entrySet().stream()
50 | .filter(nameStringToPropertyValue -> nameStringToPropertyValue.getValue().isRequired())
51 | .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
52 | return processedPropertiesMap;
53 | }
54 |
55 | private PropertyValueNode processPropertyValueNode(PropertyValueNode propertyValueNode) {
56 | PropertyValueNode newPropertyValueNode = new PropertyValueNode(propertyValueNode.getParameterLocation(), propertyValueNode.isRequired());
57 | newPropertyValueNode.setPropertiesMap(propertyValueNode.getPropertiesMap());
58 | newPropertyValueNode.setChildrenMap(propertyValueNode.getChildrenMap());
59 |
60 | if (propertyValueNode.getPropertiesMap().size() > 0) {
61 | Map processedPropertiesMap = processPropertyValues(propertyValueNode.getPropertiesMap());
62 | newPropertyValueNode.setPropertiesMap(processedPropertiesMap);
63 | }
64 |
65 | if (propertyValueNode.getChildrenMap().size() > 0) {
66 | Map processedChildrenMap = propertyValueNode.getChildrenMap().entrySet().stream()
67 | .filter(entry -> entry.getValue().isRequired())
68 | .collect(Collectors.toMap(Map.Entry::getKey, entry -> processPropertyValueNode(entry.getValue())));
69 | newPropertyValueNode.setChildrenMap(processedChildrenMap);
70 | }
71 | return newPropertyValueNode;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/fuzzing/path/PathFuzzer.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.fuzzing.path;
2 |
3 | import com.imperva.apiattacktool.fuzzing.Fuzzer;
4 |
5 | public interface PathFuzzer extends Fuzzer {
6 | }
7 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/fuzzing/value/CommonValueFuzzer.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.fuzzing.value;
2 |
3 | import com.imperva.apiattacktool.fuzzing.Fuzzer;
4 | import com.imperva.apiattacktool.model.valued.PropertyValue;
5 | import com.imperva.apiattacktool.model.valued.PropertyValueNode;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import java.util.LinkedList;
10 | import java.util.List;
11 | import java.util.Map;
12 |
13 | public class CommonValueFuzzer {
14 | private static final Logger logger = LoggerFactory.getLogger(CommonValueFuzzer.class);
15 |
16 | /**
17 | * @param propertyValueNode
18 | * @param fuzzer
19 | * @return a cloned instance with values filled in
20 | */
21 | protected PropertyValueNode traverseFuzzAndInjectPropertyValueNode(
22 | PropertyValueNode propertyValueNode, Fuzzer fuzzer) {
23 | PropertyValueNode clonedPropertyValueNode;
24 | try {
25 | clonedPropertyValueNode = (PropertyValueNode) propertyValueNode.clone();
26 | } catch (CloneNotSupportedException cloneNotSupportedException) {
27 | logger.error("Could not clone propertyValueNode: {} %n NOT GENERATING VALUE", propertyValueNode);
28 | return null;
29 | }
30 |
31 | if (clonedPropertyValueNode.getPropertiesMap().size() > 0) {
32 | fuzzAndInjectPropertyValues(clonedPropertyValueNode.getPropertiesMap(), fuzzer);
33 | }
34 |
35 | if (clonedPropertyValueNode.hasChildren()) {
36 | clonedPropertyValueNode.getChildrenMap().entrySet().forEach(
37 | stringToPropertyNodeMap ->
38 | traverseFuzzAndInjectPropertyValueNode(stringToPropertyNodeMap.getValue(), fuzzer)
39 | );
40 | }
41 | return clonedPropertyValueNode;
42 | }
43 |
44 | // Make this something that is taken from a fuzzedModelGenerator
45 | // Take the generator in c'tor of the fuzzer and use it here to traverse the arrays' propertyValueNode
46 | protected void fuzzAndInjectPropertyValues(Map nameToPropertyValueMap, Fuzzer fuzzer) {
47 | List propertiesToDeleteList = new LinkedList<>();
48 | nameToPropertyValueMap.entrySet().forEach(
49 | stringToPropertyValueEntry -> {
50 | PropertyValue propertyValue = stringToPropertyValueEntry.getValue();
51 | List valuesList = propertyValue.fuzz(fuzzer);
52 | if (valuesList != null && !valuesList.isEmpty()) {
53 | propertyValue.setValue(valuesList.get(0));
54 | } else {
55 | propertiesToDeleteList.add(stringToPropertyValueEntry.getKey());
56 | }
57 | });
58 | propertiesToDeleteList.forEach(nameToPropertyValueMap::remove);
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/fuzzing/value/NegativeSingleValueFuzzer.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.fuzzing.value;
2 |
3 | import com.imperva.apiattacktool.model.tests.ParameterLocation;
4 | import com.imperva.apiattacktool.model.valued.PropertyValueNode;
5 | import com.imperva.apiattacktool.model.valued.factory.PropertyValueFactory;
6 | import com.imperva.apispecparser.model.ArrayProperty;
7 | import com.imperva.apispecparser.model.BooleanProperty;
8 | import com.imperva.apispecparser.model.NumericProperty;
9 | import com.imperva.apispecparser.model.Property;
10 | import com.imperva.apispecparser.model.StringProperty;
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 |
14 | import java.util.ArrayList;
15 | import java.util.LinkedList;
16 | import java.util.List;
17 | import java.util.concurrent.ThreadLocalRandom;
18 |
19 | /**
20 | * Fills trivial values
21 | */
22 | public class NegativeSingleValueFuzzer extends CommonValueFuzzer implements ValueFuzzer {
23 |
24 | private static final Logger logger = LoggerFactory.getLogger(NegativeSingleValueFuzzer.class);
25 | private PropertyValueFactory propertyValueFactory;
26 |
27 | public NegativeSingleValueFuzzer(PropertyValueFactory propertyValueFactory) {
28 | this.propertyValueFactory = propertyValueFactory;
29 | }
30 |
31 | @Override
32 | public List fuzz(Property property) {
33 | /*List resultList = new ArrayList<>();
34 | resultList.add("negative untyped");
35 | return resultList;*/
36 | return null; // Disabling fuzzing, until we support file type
37 | }
38 |
39 | @Override
40 | public List fuzz(BooleanProperty booleanProperty) {
41 | String[] invalidValues = new String[]
42 | {"troo", "phalse", "tru", "Fals", "falsee", "ttrue", "tTrue", "128", "-256", "4True", "rue", "alse"};
43 | int randomValueIndex = ThreadLocalRandom.current().nextInt(invalidValues.length);
44 |
45 | List resultList = new ArrayList<>();
46 | resultList.add(invalidValues[randomValueIndex]);
47 | return resultList;
48 | }
49 |
50 | @Override
51 | public List fuzz(StringProperty stringProperty) {
52 | ThreadLocalRandom random = ThreadLocalRandom.current();
53 | List resultList = new LinkedList<>();
54 | /*if (stringProperty.getParameterLocation() == ParameterLocation.PATH) {
55 | String pathParamString = "#screwedPathParam";
56 | resultList.add(pathParamString);
57 | return resultList;
58 | }
59 |
60 | int generatedLength = 0;
61 | int minimumLength = stringProperty.getMinLength();
62 | if (minimumLength > 1) {
63 | generatedLength = minimumLength - 1;
64 | }
65 |
66 | int maximumLength = ThreadLocalRandom.current().nextInt(10) + 1;
67 | if (stringProperty.getMaxLength() != null) {
68 | maximumLength = stringProperty.getMaxLength();
69 | }
70 | if (minimumLength == 0) {
71 | generatedLength = maximumLength + 1;
72 | }
73 |
74 | int randomLengthFactor = random.nextInt(1, generatedLength);
75 | byte[] array = new byte[randomLengthFactor];
76 | random.nextBytes(array);
77 | String generatedString = new String(array, Charset.forName("UTF-16"));*/
78 | if (stringProperty.getParameterLocation() == ParameterLocation.PATH) { // Temporary hack, until we resolve how we check strings
79 | // This string is sent as is, and is not being encoded. So to fail Path param string, it is pretty straightforward (don't comply to the allowed character set in the URL).
80 | String generatedString = "{";
81 | resultList.add(generatedString);
82 | return resultList;
83 | } else {
84 | // We currently don't have a way to inject a negative value in a string. Next phase: generate negative values if it has length limits
85 | return null; // This would cause the negative fuzz to fail and be skipped.
86 | }
87 | }
88 |
89 | @Override
90 | public List fuzz(NumericProperty numericProperty) {
91 | List resultList = new ArrayList();
92 | Number randomNumber = getIncompatibleRandomNumberByType(numericProperty);
93 | resultList.add(randomNumber);
94 | return resultList;
95 | }
96 |
97 |
98 | @Override
99 | public List> fuzz(ArrayProperty arrayProperty) {
100 | return null; // Until next phase, disabling the negative fuzzing
101 | /*if (arrayProperty.getItems() == null) {
102 | return Collections.emptyList();
103 | }
104 |
105 | int generatedLength = 10;
106 | if (arrayProperty.getMaximumItems() != null) {
107 | generatedLength = arrayProperty.getMaximumItems() + 1;
108 | }
109 |
110 | if (arrayProperty.getMinimumItems() > 1) {
111 | generatedLength = arrayProperty.getMinimumItems() - 1;
112 | }
113 |
114 | PropertyNode arrayItemsPropertyNode = arrayProperty.getItems();
115 | PropertyValueNode propertyValueNode = new PropertyValueNode(arrayItemsPropertyNode, propertyValueFactory);
116 | List arrayValuesList = new LinkedList<>();
117 | for (int i = 0; i < generatedLength; i++) {
118 | PropertyValueNode fuzzedPropertyValueNode = traverseFuzzAndInjectPropertyValueNode(propertyValueNode, this);
119 | if (fuzzedPropertyValueNode == null) {
120 | logger.error("Could not clone PropertyValueNode: {}, while fuzzing. Skipping.", propertyValueNode);
121 | continue;
122 | }
123 | arrayValuesList.add(fuzzedPropertyValueNode);
124 | }
125 |
126 | List> resultList = new LinkedList<>();
127 | resultList.add(arrayValuesList);
128 | return resultList;*/
129 | }
130 |
131 | private Number getIncompatibleRandomNumberByType(NumericProperty numericProperty) {
132 | // TODO: add multipleOf handling
133 | switch (numericProperty.getType()) {
134 | case DECIMAL:
135 | case DOUBLE:
136 | case FLOAT:
137 | return ThreadLocalRandom.current().nextInt();
138 | case BASE_INTEGER:
139 | case INTEGER:
140 | default:
141 | /*float probabilityFactor = ThreadLocalRandom.current().nextFloat();
142 | int intMinimum = numericProperty.getMinimum() == null
143 | ? Integer.MIN_VALUE
144 | : numericProperty.getMinimum().intValue();
145 | int intMaximum = numericProperty.getMaximum() == null
146 | ? Integer.MAX_VALUE
147 | : numericProperty.getMaximum().intValue();
148 | if (numericProperty.getExclusiveMinimum()) {
149 | intMinimum++; // So that random boundary catches it
150 | }
151 | if (!numericProperty.getExclusiveMaximum() && intMaximum != Integer.MAX_VALUE) {
152 | intMaximum++; // So that we accidentally don't supply a valid value
153 | }
154 | if (probabilityFactor <= 0.33 && (intMinimum != Integer.MIN_VALUE || intMaximum != Integer.MAX_VALUE)) {
155 | int randomInt;
156 | if (intMinimum != Integer.MIN_VALUE) {
157 | randomInt = ThreadLocalRandom.current().nextInt(Integer.MIN_VALUE, intMinimum);
158 | } else {
159 | randomInt = ThreadLocalRandom.current().nextInt(intMaximum, Integer.MAX_VALUE);
160 | }
161 | return randomInt;
162 | }
163 | if (probabilityFactor <= 0.66) {
164 | long randomLong;
165 | if (intMinimum != Integer.MIN_VALUE) {
166 | randomLong = ThreadLocalRandom.current().nextLong(Long.MIN_VALUE, intMinimum);
167 | } else {
168 | randomLong = ThreadLocalRandom.current().nextLong(intMaximum, Long.MAX_VALUE);
169 | }
170 | return randomLong;
171 | }*/
172 | case LONG:
173 | float randomFloat = ThreadLocalRandom.current().nextFloat();
174 | return randomFloat;
175 | }
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/fuzzing/value/ValueFuzzer.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.fuzzing.value;
2 |
3 | import com.imperva.apiattacktool.fuzzing.Fuzzer;
4 |
5 | public interface ValueFuzzer extends Fuzzer {
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/infra/Tuple.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.infra;
2 |
3 | public class Tuple {
4 |
5 | public L left;
6 | public R right;
7 |
8 | public Tuple(L left, R right) {
9 | this.left = left;
10 | this.right = right;
11 | }
12 |
13 | @Override
14 | public String toString() {
15 | return "(" + String.valueOf(left) + ", " + String.valueOf(right) + ")";
16 | }
17 |
18 | @Override
19 | public boolean equals(Object obj) {
20 | if (obj == this) {
21 | return true;
22 | }
23 | if (obj instanceof Tuple) {
24 | Tuple, ?> other = (Tuple, ?>) obj;
25 | return left.equals(other.left) && right.equals(other.right);
26 | }
27 | return false;
28 | }
29 |
30 | @Override
31 | public int hashCode() {
32 | int result = 0;
33 | if (left != null) {
34 | result += (31 * result + left.hashCode());
35 | }
36 | if (right != null) {
37 | result += (31 * result + right.hashCode());
38 | }
39 | return result;
40 | }
41 |
42 | }
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/model/tests/BaseHttpResponseValidator.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.model.tests;
2 |
3 | import org.apache.commons.lang3.StringUtils;
4 |
5 | import java.util.Collection;
6 | import java.util.HashSet;
7 | import java.util.Set;
8 | import java.util.stream.Collectors;
9 |
10 | public abstract class BaseHttpResponseValidator implements HttpResponseValidator {
11 |
12 | private Set httpResponseCodes;
13 |
14 | public BaseHttpResponseValidator(Collection httpResponseCodesList) {
15 | this.httpResponseCodes = new HashSet<>(httpResponseCodesList);
16 | }
17 |
18 | @Override
19 | public abstract boolean isValidHttpCode(int httpResponseCode);
20 |
21 | protected Set getHttpResponseCodes() {
22 | return httpResponseCodes;
23 | }
24 |
25 | protected String getStringFromResponseCodeCollection(Collection responseCodeCollection) {
26 | String commaSeparatedString =
27 | responseCodeCollection.stream()
28 | .filter(responseCode -> responseCode != 0)
29 | .map(responseCode -> String.valueOf(responseCode))
30 | .collect(Collectors.joining(","));
31 | if(responseCodeCollection.contains(0)) {
32 | commaSeparatedString = commaSeparatedString + (responseCodeCollection.size() > 1 ? ", " : "") + "any";
33 | }
34 | return commaSeparatedString;
35 | }
36 |
37 | protected String buildToString(Collection userProvidedResponseCodeCollection, String scenarioOverride) {
38 | StringBuilder responseStringBuilder = new StringBuilder("Valid responses: ");
39 | String userProvidedString = getStringFromResponseCodeCollection(userProvidedResponseCodeCollection);
40 | if (!StringUtils.isBlank(userProvidedString)) {
41 | responseStringBuilder.append("(user override:");
42 | responseStringBuilder.append(userProvidedString);
43 | responseStringBuilder.append("), ");
44 | }
45 | if (!StringUtils.isBlank(responseStringBuilder)) {
46 | responseStringBuilder.append("(scenario override, not: ");
47 | responseStringBuilder.append(scenarioOverride);
48 | responseStringBuilder.append("), ");
49 | }
50 | responseStringBuilder.append(getStringFromResponseCodeCollection(getHttpResponseCodes()));
51 |
52 | return responseStringBuilder.toString();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/model/tests/EndpointTestRequestData.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.model.tests;
2 |
3 | import com.imperva.apiattacktool.model.valued.PropertyValue;
4 |
5 | import java.util.Collection;
6 | import java.util.List;
7 | import java.util.Map;
8 |
9 | public class EndpointTestRequestData {
10 | private HttpMethod httpMethod;
11 | private String fullPathWithParamBrackets; // This is for debug purposes
12 | private String endpointUrl;
13 | private Map> parameterLocationToParameterList;
14 | private String bodyString;
15 | private List consumesMimeTypes;
16 | private String testComment;
17 | private Collection httpResponseCodesCollection;
18 |
19 | public EndpointTestRequestData(HttpMethod httpMethod, String fullPathWithParamBrackets, String endpointUrl, Map> parameterLocationToParameterList, String bodyString, List consumesMimeTypes, String testComment,
21 | Collection httpResponseCodeList) {
22 | this.httpMethod = httpMethod;
23 | this.fullPathWithParamBrackets = fullPathWithParamBrackets;
24 | this.endpointUrl = endpointUrl;
25 | this.parameterLocationToParameterList = parameterLocationToParameterList;
26 | this.bodyString = bodyString;
27 | this.consumesMimeTypes = consumesMimeTypes;
28 | this.testComment = testComment;
29 | this.httpResponseCodesCollection = httpResponseCodeList;
30 | }
31 |
32 | public HttpMethod getHttpMethod() {
33 | return httpMethod;
34 | }
35 |
36 | public String getFullPathWithParamBrackets() {
37 | return fullPathWithParamBrackets;
38 | }
39 |
40 | public String getEndpointUrl() {
41 | return endpointUrl;
42 | }
43 |
44 | public boolean hasBodyParameters() {
45 | return bodyString != null && bodyString.length() > 0;
46 | }
47 |
48 | public boolean hasHeaderParameters() {
49 | return hasParameterInLocation(ParameterLocation.HEADER);
50 | }
51 |
52 | public boolean hasQueryParameters() {
53 | return hasParameterInLocation(ParameterLocation.QUERY);
54 | }
55 |
56 | public boolean hasCookieParameters() {
57 | return hasParameterInLocation(ParameterLocation.COOKIE);
58 | }
59 |
60 | public boolean hasFormDataParameters() {
61 | return hasParameterInLocation(ParameterLocation.FORMDATA);
62 | }
63 |
64 | public String getBodyParameter() {
65 | return bodyString;
66 | }
67 |
68 | public List getHeaderParameters() {
69 | return parameterLocationToParameterList.get(ParameterLocation.HEADER);
70 | }
71 |
72 | public List getQueryParameters() {
73 | return parameterLocationToParameterList.get(ParameterLocation.QUERY);
74 | }
75 |
76 | public List getFormDataParameters() {
77 | return parameterLocationToParameterList.get(ParameterLocation.FORMDATA);
78 | }
79 |
80 | public List getConsumesMimeTypes() {
81 | return consumesMimeTypes;
82 | }
83 |
84 | public Collection getHttpResponseCodesCollection() {
85 | return httpResponseCodesCollection;
86 | }
87 |
88 | private boolean hasParameterInLocation(ParameterLocation location) {
89 | return parameterLocationToParameterList.get(location) != null && parameterLocationToParameterList.get(location).size() > 0;
90 | }
91 |
92 | public String getTestComment() {
93 | return testComment;
94 | }
95 |
96 | @Override
97 | public String toString() {
98 | return "EndpointTestRequestData{"
99 | + httpMethod + " " + endpointUrl
100 | + ", parametersByLocation=" + parameterLocationToParameterList
101 | + ", bodyString='" + bodyString + '\''
102 | + '}';
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/model/tests/HttpMethod.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.model.tests;
2 |
3 | public enum HttpMethod {
4 | POST,
5 | GET,
6 | PUT,
7 | PATCH,
8 | DELETE,
9 | HEAD,
10 | OPTIONS
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/model/tests/HttpRequestWrapper.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.model.tests;
2 |
3 | import org.apache.http.HttpRequest;
4 |
5 | public class HttpRequestWrapper {
6 |
7 | private HttpRequest httpRequest;
8 | private String testElementComment;
9 | private HttpResponseValidator httpResponseValidator;
10 |
11 | public HttpRequestWrapper(HttpRequest httpRequest, String testElementComment, HttpResponseValidator httpResponseValidator) {
12 | this.httpRequest = httpRequest;
13 | this.testElementComment = testElementComment;
14 | this.httpResponseValidator = httpResponseValidator;
15 | }
16 |
17 | public HttpRequest getHttpRequest() {
18 | return httpRequest;
19 | }
20 |
21 | public String getTestElementComment() {
22 | return testElementComment;
23 | }
24 |
25 | public HttpResponseValidator getHttpResponseValidator() {
26 | return httpResponseValidator;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/model/tests/HttpResponseValidator.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.model.tests;
2 |
3 | public interface HttpResponseValidator {
4 | boolean isValidHttpCode(int httpResponseCode);
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/model/tests/NegativeTestHttpResponseValidator.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.model.tests;
2 |
3 | import com.imperva.apiattacktool.tests.TestConfiguration;
4 |
5 | import java.util.Collection;
6 |
7 | public class NegativeTestHttpResponseValidator extends BaseHttpResponseValidator {
8 |
9 | public NegativeTestHttpResponseValidator(Collection httpResponseCodesList) {
10 | super(httpResponseCodesList);
11 | }
12 |
13 | @Override
14 | public boolean isValidHttpCode(int httpResponseCode) {
15 | if (TestConfiguration.getUserProvidedNegativeResponseCodes().contains(httpResponseCode)) {
16 | return true;
17 | }
18 | if (httpResponseCode < 300 || httpResponseCode >= 500) {
19 | return false;
20 | }
21 | if (getHttpResponseCodes().contains(0)) {
22 | return true;
23 | }
24 |
25 | return getHttpResponseCodes().contains(httpResponseCode);
26 | }
27 |
28 | @Override
29 | public String toString() {
30 | return buildToString(TestConfiguration.getUserProvidedNegativeResponseCodes(), "1xx,2xx,5xx");
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/model/tests/ParameterLocation.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.model.tests;
2 |
3 | public enum ParameterLocation {
4 | HEADER,
5 | COOKIE,
6 | PATH,
7 | QUERY,
8 | BODY,
9 | FORMDATA
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/model/tests/PositiveTestHttpResponseValidator.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.model.tests;
2 |
3 | import com.imperva.apiattacktool.tests.TestConfiguration;
4 |
5 | import java.util.Collection;
6 |
7 | public class PositiveTestHttpResponseValidator extends BaseHttpResponseValidator {
8 |
9 | public PositiveTestHttpResponseValidator(Collection httpResponseCodesList) {
10 | super(httpResponseCodesList);
11 | }
12 |
13 | @Override
14 | public boolean isValidHttpCode(int httpResponseCode) {
15 | if (TestConfiguration.getUserProvidedPositiveResponseCodes().contains(httpResponseCode)) {
16 | return true;
17 | }
18 | if (httpResponseCode >= 500) {
19 | return false;
20 | }
21 | if (getHttpResponseCodes().contains(0)) {
22 | return true;
23 | }
24 |
25 | return getHttpResponseCodes().contains(httpResponseCode);
26 | }
27 |
28 | @Override
29 | public String toString() {
30 | return buildToString(TestConfiguration.getUserProvidedPositiveResponseCodes(), "5xx");
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/model/valued/ArrayPropertyValue.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.model.valued;
2 |
3 | import com.imperva.apiattacktool.fuzzing.Fuzzer;
4 | import com.imperva.apispecparser.model.ArrayProperty;
5 | import com.imperva.apispecparser.model.Property;
6 |
7 | import java.util.HashMap;
8 | import java.util.List;
9 | import java.util.Map;
10 | import java.util.stream.Collectors;
11 |
12 | public class ArrayPropertyValue extends ArrayProperty implements PropertyValue> {
13 |
14 | private List value;
15 |
16 |
17 | public ArrayPropertyValue(ArrayProperty arrayProperty, List items) {
18 | super(new Property(arrayProperty.getParameterLocation(), arrayProperty.getType(), arrayProperty.getName(), arrayProperty.isRequired(),
19 | arrayProperty.getReadOnly(), arrayProperty.getAllowEmptyValue()),
20 | arrayProperty.getAreItemsUnique(), arrayProperty.getItems(), arrayProperty.getMinimumItems(), arrayProperty.getMaximumItems(),
21 | arrayProperty.getCollectionFormat().getFormatString());
22 | this.value = items;
23 | }
24 |
25 | @Override
26 | public Object clone() throws CloneNotSupportedException {
27 | return super.clone();
28 | }
29 |
30 | @Override
31 | public void setValue(List value) {
32 | this.value = value;
33 | }
34 |
35 | @Override
36 | public List getValue() {
37 | return value;
38 | }
39 |
40 | @Override
41 | public List> fuzz(Fuzzer fuzzer) {
42 | return fuzzer.fuzz(this);
43 | }
44 |
45 | @Override
46 | public Map bodyParameterJsonRepresentationMap() {
47 | HashMap representationMap = new HashMap<>(1);
48 | representationMap.put(this.getName(), value.stream().map(PropertyValueNode::bodyParameterJsonRepresentationMap).collect(Collectors.toList()));
49 | return representationMap;
50 | }
51 |
52 | @Override
53 | public String toString() {
54 | return "ArrayPropertyValue{"
55 | + "value=" + value
56 | + ", " + super.toString() + '}';
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/model/valued/ArrayPropertyValueAdapter.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.model.valued;
2 |
3 | import com.imperva.apiattacktool.fuzzing.Fuzzer;
4 | import com.imperva.apiattacktool.model.tests.ParameterLocation;
5 | import com.imperva.apispecparser.model.PropertyType;
6 |
7 | import java.util.List;
8 | import java.util.Map;
9 | import java.util.stream.Collectors;
10 |
11 | /**
12 | * An adapter to adapt getValue to return a string, whereas the array items property is represented by PropertyValueNode
13 | * It should be used in the values translation phase
14 | */
15 | public class ArrayPropertyValueAdapter implements PropertyValue {
16 |
17 | private ArrayPropertyValue arrayPropertyValue;
18 |
19 | public ArrayPropertyValueAdapter(ArrayPropertyValue arrayPropertyValue) {
20 | this.arrayPropertyValue = arrayPropertyValue;
21 | }
22 |
23 | @Override
24 | public String getName() {
25 | return arrayPropertyValue.getName();
26 | }
27 |
28 | @Override
29 | public ParameterLocation getParameterLocation() {
30 | return arrayPropertyValue.getParameterLocation();
31 | }
32 |
33 | @Override
34 | public PropertyType getType() {
35 | return arrayPropertyValue.getType();
36 | }
37 |
38 | @Override
39 | public Object clone() throws CloneNotSupportedException {
40 | return arrayPropertyValue.clone();
41 | }
42 |
43 | @Override
44 | public String getValue() {
45 | List propertyValueNodeList = arrayPropertyValue.getValue();
46 | if (propertyValueNodeList != null && !propertyValueNodeList.isEmpty()) {
47 | String delimiterSeparatedArrayValues =
48 | propertyValueNodeList.stream()
49 | .map(propertyValueNode ->
50 | String.valueOf(
51 | propertyValueNode.getPropertiesMap().entrySet().stream().findFirst().get().getValue().getValue()))
52 | .collect(Collectors.joining(arrayPropertyValue.getCollectionFormat().getOutputString()));
53 | return delimiterSeparatedArrayValues;
54 | }
55 | return "";
56 | }
57 |
58 | @Override
59 | public void setValue(String value) {
60 | throw new IllegalStateException();
61 | }
62 |
63 | @Override
64 | public boolean isRequired() {
65 | return arrayPropertyValue.isRequired();
66 | }
67 |
68 | @Override
69 | public List fuzz(Fuzzer fuzzer) {
70 | throw new IllegalStateException();
71 | }
72 |
73 | @Override
74 | public Map bodyParameterJsonRepresentationMap() {
75 | return arrayPropertyValue.bodyParameterJsonRepresentationMap();
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/model/valued/BooleanPropertyValue.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.model.valued;
2 |
3 | import com.imperva.apiattacktool.fuzzing.Fuzzer;
4 | import com.imperva.apispecparser.model.BooleanProperty;
5 | import com.imperva.apispecparser.model.Property;
6 |
7 | import java.util.List;
8 |
9 | public class BooleanPropertyValue extends BooleanProperty implements PropertyValue {
10 |
11 | String value;
12 |
13 | public BooleanPropertyValue(BooleanProperty booleanProperty, String value) {
14 | super(new Property(booleanProperty.getParameterLocation(), booleanProperty.getType(), booleanProperty.getName(),
15 | booleanProperty.isRequired(), booleanProperty.getReadOnly(), booleanProperty.getAllowEmptyValue()),
16 | booleanProperty.getEnumList());
17 | this.value = value;
18 | }
19 |
20 | @Override
21 | public void setValue(String value) {
22 | this.value = value;
23 | }
24 |
25 | @Override
26 | public String getValue() {
27 | return value;
28 | }
29 |
30 | @Override
31 | public List fuzz(Fuzzer fuzzer) {
32 | return fuzzer.fuzz(this);
33 | }
34 |
35 | @Override
36 | public String toString() {
37 | return "BooleanPropertyValue{"
38 | + "value='" + value + '\''
39 | + ", " + super.toString() + '}';
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/model/valued/EndpointValuedModel.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.model.valued;
2 |
3 | import com.imperva.apiattacktool.model.tests.HttpMethod;
4 | import com.imperva.apiattacktool.model.valued.factory.PropertyValueFactory;
5 | import com.imperva.apispecparser.model.EndpointModel;
6 | import com.imperva.apispecparser.model.Property;
7 |
8 | import java.util.Collection;
9 | import java.util.LinkedList;
10 | import java.util.List;
11 | import java.util.Map;
12 | import java.util.stream.Collectors;
13 |
14 | public class EndpointValuedModel implements Cloneable {
15 |
16 | private String fullPathWithParamBrackets;
17 | private HttpMethod httpMethod;
18 | private List consumes;
19 | private PropertyValueNode propertyValueNode;
20 | private String testComment = "";
21 | private Collection httpResponseCodesCollection;
22 |
23 | public EndpointValuedModel(EndpointModel endpointModel, PropertyValueFactory propertyValueFactory) {
24 | this.fullPathWithParamBrackets = endpointModel.getFullPathWithParamBrackets();
25 | this.httpMethod = endpointModel.getHttpMethod();
26 | this.consumes = endpointModel.getConsumes();
27 | this.propertyValueNode = new PropertyValueNode(null, true);
28 |
29 | endpointModel.getSimpleParametersMap().entrySet().forEach(
30 | nameToPropertyMapEntry -> {
31 | this.propertyValueNode.getPropertiesMap().put(nameToPropertyMapEntry.getKey(),
32 | convertPropertyToPropertyValue(nameToPropertyMapEntry.getValue(), propertyValueFactory));
33 | });
34 |
35 | endpointModel.getChildrenMap().entrySet().forEach(nameToPropertyNodeMap -> {
36 | this.propertyValueNode.getChildrenMap().put(
37 | nameToPropertyNodeMap.getKey(), new PropertyValueNode(nameToPropertyNodeMap.getValue(), propertyValueFactory));
38 | });
39 |
40 | this.httpResponseCodesCollection = endpointModel.getHttpResponseCodesList().stream()
41 | .map(httpResponseCode -> new Integer(httpResponseCode))
42 | .collect(Collectors.toList());
43 | }
44 |
45 | private EndpointValuedModel() {
46 | this.propertyValueNode = new PropertyValueNode(null, true);
47 | }
48 |
49 | public String getFullPathWithParamBrackets() {
50 | return fullPathWithParamBrackets;
51 | }
52 |
53 | public HttpMethod getHttpMethod() {
54 | return httpMethod;
55 | }
56 |
57 | public List getConsumes() {
58 | return consumes;
59 | }
60 |
61 | public PropertyValueNode getPropertyValueNode() {
62 | return propertyValueNode;
63 | }
64 |
65 | public void setPropertyValueNode(PropertyValueNode propertyValueNode) {
66 | this.propertyValueNode = propertyValueNode;
67 | }
68 |
69 | public Map getPropertiesMap() {
70 | return propertyValueNode.getPropertiesMap();
71 | }
72 |
73 | public Map getChildrenMap() {
74 | return propertyValueNode.getChildrenMap();
75 | }
76 |
77 | public String getTestComment() {
78 | return testComment;
79 | }
80 |
81 | public void setTestComment(String testComment) {
82 | this.testComment = testComment;
83 | }
84 |
85 | public Collection getHttpResponseCodesCollection() {
86 | return httpResponseCodesCollection;
87 | }
88 |
89 | @Override
90 | public Object clone() throws CloneNotSupportedException {
91 | EndpointValuedModel newEndpointValuedModel = new EndpointValuedModel();
92 | newEndpointValuedModel.fullPathWithParamBrackets = this.fullPathWithParamBrackets;
93 | newEndpointValuedModel.httpMethod = this.httpMethod;
94 | newEndpointValuedModel.consumes = new LinkedList<>(this.consumes);
95 | newEndpointValuedModel.propertyValueNode = new PropertyValueNode(this.propertyValueNode.getParameterLocation(), this.propertyValueNode.isRequired());
96 |
97 | // Keys are not cloned, as they are not meant to be changed
98 | for (Map.Entry entry : this.getPropertiesMap().entrySet()) {
99 | newEndpointValuedModel.propertyValueNode.getPropertiesMap().put(entry.getKey(), (PropertyValue) entry.getValue().clone());
100 | }
101 |
102 | for (Map.Entry entry : this.getChildrenMap().entrySet()) {
103 | newEndpointValuedModel.propertyValueNode.getChildrenMap().put(entry.getKey(), (PropertyValueNode) entry.getValue().clone());
104 | }
105 |
106 | newEndpointValuedModel.httpResponseCodesCollection = new LinkedList<>(this.httpResponseCodesCollection);
107 | return newEndpointValuedModel;
108 | }
109 |
110 | private PropertyValue convertPropertyToPropertyValue(Property property, PropertyValueFactory propertyValueFactory) {
111 | return propertyValueFactory.getPropertyValueFromProperty(property);
112 | }
113 |
114 | @Override
115 | public String toString() {
116 | return "EndpointValuedModel{"
117 | + "fullPathWithParamBrackets='" + fullPathWithParamBrackets + '\''
118 | + ", httpMethod=" + httpMethod
119 | + ", propertyValueNode=" + propertyValueNode
120 | + '}';
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/model/valued/NumericPropertyValue.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.model.valued;
2 |
3 | import com.imperva.apiattacktool.fuzzing.Fuzzer;
4 | import com.imperva.apispecparser.model.NumericProperty;
5 | import com.imperva.apispecparser.model.Property;
6 |
7 | import java.util.List;
8 |
9 | public class NumericPropertyValue extends NumericProperty implements PropertyValue {
10 |
11 | private Number value;
12 |
13 | public NumericPropertyValue(NumericProperty numericProperty, Number value) {
14 | super(new Property(numericProperty.getParameterLocation(), numericProperty.getType(), numericProperty.getName(),
15 | numericProperty.isRequired(), numericProperty.getReadOnly(), numericProperty.getAllowEmptyValue()),
16 | numericProperty.getEnumList(), numericProperty.getMinimum(), numericProperty.getMaximum(), numericProperty.getMultipleOf(),
17 | numericProperty.getExclusiveMinimum(), numericProperty.getExclusiveMaximum());
18 | this.value = value;
19 | }
20 |
21 | @Override
22 | public Object clone() throws CloneNotSupportedException {
23 | return super.clone();
24 | }
25 |
26 | @Override
27 | public void setValue(Number value) {
28 | this.value = value;
29 | }
30 |
31 | @Override
32 | public Number getValue() {
33 | return value;
34 | }
35 |
36 | @Override
37 | public List fuzz(Fuzzer fuzzer) {
38 | return fuzzer.fuzz(this);
39 | }
40 |
41 | @Override
42 | public String toString() {
43 | return "NumericPropertyValue{"
44 | + "value=" + value
45 | + ", " + super.toString() + '}';
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/model/valued/PropertyPropertyValue.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.model.valued;
2 |
3 | import com.imperva.apiattacktool.fuzzing.Fuzzer;
4 | import com.imperva.apispecparser.model.Property;
5 |
6 | import java.util.List;
7 |
8 | public class PropertyPropertyValue extends Property implements PropertyValue {
9 |
10 | private String value;
11 |
12 | public PropertyPropertyValue(Property property, String value) {
13 | super(property);
14 | this.value = value;
15 | }
16 |
17 | @Override
18 | public Object clone() throws CloneNotSupportedException {
19 | return super.clone();
20 | }
21 |
22 | @Override
23 | public void setValue(String value) {
24 | this.value = value;
25 | }
26 |
27 | @Override
28 | public String getValue() {
29 | return value;
30 | }
31 |
32 | @Override
33 | public List fuzz(Fuzzer fuzzer) {
34 | return fuzzer.fuzz(this);
35 | }
36 |
37 | @Override
38 | public String toString() {
39 | return "PropertyPropertyValue{"
40 | + "value='" + value + '\''
41 | + ", Property=" + super.toString() + '}';
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/model/valued/PropertyValue.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.model.valued;
2 |
3 | import com.imperva.apiattacktool.fuzzing.Fuzzer;
4 | import com.imperva.apiattacktool.model.tests.ParameterLocation;
5 | import com.imperva.apispecparser.model.PropertyType;
6 |
7 | import java.util.HashMap;
8 | import java.util.List;
9 | import java.util.Map;
10 |
11 | public interface PropertyValue extends Cloneable {
12 | String getName();
13 |
14 | ParameterLocation getParameterLocation();
15 |
16 | PropertyType getType();
17 |
18 | Object clone() throws CloneNotSupportedException;
19 |
20 | T getValue();
21 |
22 | void setValue(T value);
23 |
24 | boolean isRequired();
25 |
26 | List fuzz(Fuzzer fuzzer); // Visitor DP, accept method
27 |
28 | // https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
29 | // You want to specify the behavior of a particular data type, but not concerned about who implements its behavior
30 | // You want to take advantage of multiple inheritance of type
31 | default Map bodyParameterJsonRepresentationMap() {
32 | HashMap representationMap = new HashMap<>(1);
33 | representationMap.put(this.getName(), this.getValue());
34 | return representationMap;
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/model/valued/PropertyValueNode.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.model.valued;
2 |
3 | import com.imperva.apiattacktool.model.tests.ParameterLocation;
4 | import com.imperva.apiattacktool.model.valued.factory.PropertyValueFactory;
5 | import com.imperva.apispecparser.model.Property;
6 | import com.imperva.apispecparser.model.PropertyNode;
7 |
8 | import java.util.HashMap;
9 | import java.util.Map;
10 |
11 | public class PropertyValueNode implements Cloneable {
12 |
13 | private ParameterLocation parameterLocation;
14 | private boolean isRequired;
15 | private Map propertyNameToPropertyValueMap;
16 | private Map propertyNameToPropertyValueNodeMap;
17 |
18 | public PropertyValueNode(ParameterLocation parameterLocation, boolean isRequired) {
19 | this.parameterLocation = parameterLocation;
20 | this.isRequired = isRequired;
21 | this.propertyNameToPropertyValueNodeMap = new HashMap<>();
22 | this.propertyNameToPropertyValueMap = new HashMap<>();
23 | }
24 |
25 | public PropertyValueNode(PropertyNode propertyNode, PropertyValueFactory propertyValueFactory) {
26 | PropertyValueNode propertyValueNode = traverseNodeConvertToPropertyValue(propertyNode, propertyValueFactory);
27 | this.parameterLocation = propertyValueNode.getParameterLocation();
28 | this.isRequired = propertyValueNode.isRequired();
29 | this.propertyNameToPropertyValueMap = propertyValueNode.propertyNameToPropertyValueMap;
30 | this.propertyNameToPropertyValueNodeMap = propertyValueNode.propertyNameToPropertyValueNodeMap;
31 | }
32 |
33 | public void addPropertyValueType(String propertyName, PropertyValue property) {
34 | propertyNameToPropertyValueMap.put(propertyName, property);
35 | }
36 |
37 | public void addPropertyNode(String propertyName, PropertyValueNode propertyNode) {
38 | propertyNameToPropertyValueNodeMap.put(propertyName, propertyNode);
39 | }
40 |
41 | public ParameterLocation getParameterLocation() {
42 | return parameterLocation;
43 | }
44 |
45 | public boolean isRequired() {
46 | return isRequired;
47 | }
48 |
49 | public Map getPropertiesMap() {
50 | return propertyNameToPropertyValueMap;
51 | }
52 |
53 | public void setPropertiesMap(Map propertyNameToPropertyValueMap) {
54 | this.propertyNameToPropertyValueMap = propertyNameToPropertyValueMap;
55 | }
56 |
57 | public boolean hasChildren() {
58 | return propertyNameToPropertyValueNodeMap.size() > 0;
59 | }
60 |
61 | public Map getChildrenMap() {
62 | return propertyNameToPropertyValueNodeMap;
63 | }
64 |
65 | public void setChildrenMap(Map propertyNameToPropertyValueNodeMap) {
66 | this.propertyNameToPropertyValueNodeMap = propertyNameToPropertyValueNodeMap;
67 | }
68 |
69 | @Override
70 | public Object clone() throws CloneNotSupportedException {
71 | PropertyValueNode propertyValueNode = new PropertyValueNode(this.parameterLocation, this.isRequired);
72 |
73 | for (Map.Entry entry : propertyNameToPropertyValueMap.entrySet()) {
74 | propertyValueNode.propertyNameToPropertyValueMap.put(entry.getKey(), (PropertyValue) entry.getValue().clone());
75 | }
76 |
77 | for (Map.Entry entry : propertyNameToPropertyValueNodeMap.entrySet()) {
78 | propertyValueNode.propertyNameToPropertyValueNodeMap.put(entry.getKey(), (PropertyValueNode) entry.getValue().clone());
79 | }
80 |
81 | return propertyValueNode;
82 | }
83 |
84 | public Map bodyParameterJsonRepresentationMap() {
85 | Map jsonRepresentationMap =
86 | new HashMap<>(propertyNameToPropertyValueMap.size() + propertyNameToPropertyValueNodeMap.size());
87 | propertyNameToPropertyValueMap.entrySet().stream()
88 | .filter(stringPropertyValueEntry -> stringPropertyValueEntry.getValue().getParameterLocation() == ParameterLocation.BODY)
89 | .forEach(stringToPropertyValueEntry ->
90 | jsonRepresentationMap.putAll(stringToPropertyValueEntry.getValue().bodyParameterJsonRepresentationMap()));
91 |
92 | propertyNameToPropertyValueNodeMap.entrySet().stream()
93 | .filter(stringPropertyValueEntry -> stringPropertyValueEntry.getValue().getParameterLocation() == ParameterLocation.BODY)
94 | .forEach(
95 | stringPropertyToValueNodeEntry ->
96 | jsonRepresentationMap.put(stringPropertyToValueNodeEntry.getKey(),
97 | stringPropertyToValueNodeEntry.getValue().bodyParameterJsonRepresentationMap()));
98 | return jsonRepresentationMap;
99 | }
100 |
101 | @Override
102 | public String toString() {
103 | return "PropertyValueNode{"
104 | + "propertyNameToPropertyValueMap=" + propertyNameToPropertyValueMap
105 | + ", propertyNameToPropertyValueNodeMap=" + propertyNameToPropertyValueNodeMap
106 | + '}';
107 | }
108 |
109 | private PropertyValue convertPropertyToPropertyValue(Property property, PropertyValueFactory propertyValueFactory) {
110 | return propertyValueFactory.getPropertyValueFromProperty(property);
111 | }
112 |
113 | private PropertyValueNode traverseNodeConvertToPropertyValue(PropertyNode propertyNode, PropertyValueFactory propertyValueFactory) {
114 | PropertyValueNode propertyValueNode = new PropertyValueNode(propertyNode.getParameterLocation(), propertyNode.isRequired());
115 | if (propertyNode.getPropertiesMap().size() > 0) {
116 | propertyNode.getPropertiesMap().entrySet().forEach(
117 | locatorToPropertyMapEntry -> {
118 | propertyValueNode.addPropertyValueType(locatorToPropertyMapEntry.getKey(),
119 | convertPropertyToPropertyValue(locatorToPropertyMapEntry.getValue(), propertyValueFactory));
120 | });
121 | }
122 | if (propertyNode.hasChildren()) {
123 | propertyNode.getChildrenMap().entrySet().forEach(
124 | locatorToPropertyNodeMap -> {
125 | PropertyValueNode convertedPropertyValueNode = traverseNodeConvertToPropertyValue(locatorToPropertyNodeMap.getValue(),
126 | propertyValueFactory);
127 | propertyValueNode.addPropertyNode(locatorToPropertyNodeMap.getKey(), convertedPropertyValueNode);
128 | }
129 | );
130 | }
131 | return propertyValueNode;
132 | }
133 |
134 | }
135 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/model/valued/StringPropertyValue.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.model.valued;
2 |
3 | import com.imperva.apiattacktool.fuzzing.Fuzzer;
4 | import com.imperva.apispecparser.model.Property;
5 | import com.imperva.apispecparser.model.StringProperty;
6 |
7 | import java.util.List;
8 |
9 | public class StringPropertyValue extends StringProperty implements PropertyValue {
10 |
11 | private String value;
12 |
13 | public StringPropertyValue(StringProperty stringProperty, String value) {
14 | super(new Property(stringProperty.getParameterLocation(), stringProperty.getType(), stringProperty.getName(), stringProperty.isRequired(),
15 | stringProperty.getReadOnly(), stringProperty.getAllowEmptyValue()),
16 | stringProperty.getEnumList(), stringProperty.getMinLength(), stringProperty.getMaxLength(), stringProperty.getPattern());
17 | this.value = value;
18 | }
19 |
20 | @Override
21 | public Object clone() throws CloneNotSupportedException {
22 | return super.clone();
23 | }
24 |
25 | @Override
26 | public void setValue(String value) {
27 | this.value = value;
28 | }
29 |
30 | @Override
31 | public String getValue() {
32 | return value;
33 | }
34 |
35 | @Override
36 | public List fuzz(Fuzzer fuzzer) {
37 | return fuzzer.fuzz(this);
38 | }
39 |
40 | @Override
41 | public String toString() {
42 | return "StringPropertyValue{"
43 | + "value='" + value + '\''
44 | + ", " + super.toString() + '}';
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/model/valued/factory/PropertyValueFactory.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.model.valued.factory;
2 |
3 | import com.imperva.apiattacktool.model.valued.PropertyValue;
4 | import com.imperva.apispecparser.model.Property;
5 |
6 | public interface PropertyValueFactory {
7 | PropertyValue getPropertyValueFromProperty(Property property);
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/model/valued/factory/SimplePropertyValueFactory.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.model.valued.factory;
2 |
3 | import com.imperva.apiattacktool.model.valued.ArrayPropertyValue;
4 | import com.imperva.apiattacktool.model.valued.BooleanPropertyValue;
5 | import com.imperva.apiattacktool.model.valued.NumericPropertyValue;
6 | import com.imperva.apiattacktool.model.valued.PropertyPropertyValue;
7 | import com.imperva.apiattacktool.model.valued.PropertyValue;
8 | import com.imperva.apiattacktool.model.valued.StringPropertyValue;
9 | import com.imperva.apispecparser.model.ArrayProperty;
10 | import com.imperva.apispecparser.model.BooleanProperty;
11 | import com.imperva.apispecparser.model.NumericProperty;
12 | import com.imperva.apispecparser.model.Property;
13 | import com.imperva.apispecparser.model.StringProperty;
14 |
15 | public class SimplePropertyValueFactory implements PropertyValueFactory {
16 |
17 | @Override
18 | public PropertyValue getPropertyValueFromProperty(Property property) {
19 | if (property == null) {
20 | return null;
21 | }
22 |
23 | switch (property.getType()) {
24 | case ARRAY:
25 | ArrayProperty arrayProperty = (ArrayProperty) property;
26 | return new ArrayPropertyValue(arrayProperty, null);
27 | case FLOAT:
28 | case LONG:
29 | case DECIMAL:
30 | case DOUBLE:
31 | case BASE_INTEGER:
32 | case INTEGER:
33 | NumericProperty numericProperty = (NumericProperty) property;
34 | return new NumericPropertyValue(numericProperty, null);
35 | case UUID:
36 | case PASSWORD:
37 | case EMAIL:
38 | case DATETIME:
39 | case DATE:
40 | // As awkward this may sound. We should convert the (enum values) to Date using a dedicated active propertynode, instead of this circus
41 | case BINARY:
42 | case STRING:
43 | case BYTE_ARRAY:
44 | StringProperty stringProperty = (StringProperty) property;
45 | return new StringPropertyValue(stringProperty, null);
46 | case BOOLEAN:
47 | BooleanProperty booleanProperty = (BooleanProperty) property;
48 | return new BooleanPropertyValue(booleanProperty, null);
49 | case UNTYPED:
50 | case FILE:
51 | default:
52 | return new PropertyPropertyValue(property, null);
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/processors/EndpointModelProcessor.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.processors;
2 |
3 | import com.imperva.apiattacktool.fuzzing.Fuzzer;
4 | import com.imperva.apiattacktool.model.valued.EndpointValuedModel;
5 |
6 | import java.util.List;
7 |
8 | public interface EndpointModelProcessor {
9 | List process(List endpointModelList, Fuzzer fuzzer);
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/processors/FuzzEndpointModelProcessor.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.processors;
2 |
3 | import com.imperva.apiattacktool.fuzzing.Fuzzer;
4 | import com.imperva.apiattacktool.fuzzing.modelgenerators.FuzzedModelsGenerator;
5 | import com.imperva.apiattacktool.model.valued.EndpointValuedModel;
6 | import com.imperva.apiattacktool.model.valued.factory.PropertyValueFactory;
7 |
8 | import java.util.Collections;
9 | import java.util.List;
10 | import java.util.stream.Collectors;
11 |
12 | public class FuzzEndpointModelProcessor implements EndpointModelProcessor {
13 |
14 | private FuzzedModelsGenerator fuzzedModelsGenerator;
15 | private PropertyValueFactory propertyValueFactory;
16 |
17 | public FuzzEndpointModelProcessor(FuzzedModelsGenerator fuzzedModelsGenerator) {
18 | this.fuzzedModelsGenerator = fuzzedModelsGenerator;
19 | this.propertyValueFactory = fuzzedModelsGenerator.getPropertyValueFactory();
20 | }
21 |
22 | @Override
23 | public List process(List endpointModelList, Fuzzer fuzzer) {
24 | if (endpointModelList == null) {
25 | return Collections.EMPTY_LIST;
26 | }
27 |
28 | return endpointModelList.stream()
29 | .flatMap(endpointValuedModel -> fuzzedModelsGenerator.fuzzModelValues(
30 | endpointValuedModel, fuzzer).stream())
31 | .collect(Collectors.toList());
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/tests/AbstractTestDriver.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.tests;
2 |
3 | import com.imperva.apiattacktool.activators.HttpRequestGenerator;
4 | import com.imperva.apiattacktool.activators.ModelToValueConverter;
5 | import com.imperva.apiattacktool.activators.RequestDataConverter;
6 | import com.imperva.apiattacktool.fuzzing.Fuzzer;
7 | import com.imperva.apiattacktool.fuzzing.parameters.PolicyEnforcer;
8 | import com.imperva.apiattacktool.processors.EndpointModelProcessor;
9 | import com.imperva.apispecparser.exceptions.ParseException;
10 | import com.imperva.apispecparser.model.EndpointModel;
11 | import com.imperva.apispecparser.parsers.ApiSpecFileLocation;
12 | import com.imperva.apispecparser.parsers.swagger.Swagger2Parser;
13 | import com.imperva.apispecparser.utils.FileUtils;
14 | import org.slf4j.Logger;
15 | import org.slf4j.LoggerFactory;
16 |
17 | import java.io.IOException;
18 | import java.util.Collections;
19 | import java.util.List;
20 |
21 | public class AbstractTestDriver {
22 | private static final Logger logger = LoggerFactory.getLogger(AbstractTestDriver.class);
23 |
24 | private ModelToValueConverter modelToValueConverter;
25 | private PolicyEnforcer policyEnforcer;
26 | private EndpointModelProcessor beforeMainEndpointModelProcessor;
27 | private EndpointModelProcessor mainEndpointModelProcessor;
28 | private RequestDataConverter testRequestDataConverter;
29 | private HttpRequestGenerator httpRequestGenerator;
30 | private Fuzzer fuzzer;
31 |
32 | public AbstractTestDriver(ModelToValueConverter modelToValueConverter,
33 | PolicyEnforcer policyEnforcer,
34 | EndpointModelProcessor beforeMainEndpointModelProcessor,
35 | EndpointModelProcessor mainEndpointModelProcessor,
36 | RequestDataConverter testRequestDataConverter,
37 | HttpRequestGenerator httpRequestGenerator,
38 | Fuzzer fuzzer) {
39 | this.modelToValueConverter = modelToValueConverter;
40 | this.policyEnforcer = policyEnforcer;
41 | this.beforeMainEndpointModelProcessor = beforeMainEndpointModelProcessor;
42 | this.mainEndpointModelProcessor = mainEndpointModelProcessor;
43 | this.testRequestDataConverter = testRequestDataConverter;
44 | this.httpRequestGenerator = httpRequestGenerator;
45 | this.fuzzer = fuzzer;
46 | }
47 |
48 | public ModelToValueConverter getModelToValueConverter() {
49 | return modelToValueConverter;
50 | }
51 |
52 | public PolicyEnforcer getPolicyEnforcer() {
53 | return policyEnforcer;
54 | }
55 |
56 | public EndpointModelProcessor getBeforeMainEndpointModelProcessor() {
57 | return beforeMainEndpointModelProcessor;
58 | }
59 |
60 | public EndpointModelProcessor getMainEndpointModelProcessor() {
61 | return mainEndpointModelProcessor;
62 | }
63 |
64 | public RequestDataConverter getTestRequestDataConverter() {
65 | return testRequestDataConverter;
66 | }
67 |
68 | public HttpRequestGenerator getHttpRequestGenerator() {
69 | return httpRequestGenerator;
70 | }
71 |
72 | public Fuzzer getFuzzer() {
73 | return fuzzer;
74 | }
75 |
76 | protected String loadResourceFileAsString(String resourceFileName) throws IOException {
77 | return FileUtils.readResource(resourceFileName);
78 | }
79 |
80 | protected List parseSwagger(String resourceFileName) {
81 | List endpointModelList;
82 | Swagger2Parser swagger2Parser = new Swagger2Parser();
83 |
84 | try {
85 | endpointModelList = swagger2Parser.getEndpointModelList(resourceFileName, ApiSpecFileLocation.EXTERNAL);
86 | } catch (ParseException parseException) {
87 | logger.error("Error parsing swagger: {}", parseException.getMessage());
88 | return Collections.emptyList();
89 | }
90 | return endpointModelList;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/tests/NegativeSinglePropertyScenarioTestDriver.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.tests;
2 |
3 | import com.imperva.apiattacktool.activators.EndpointModelToValueConverter;
4 | import com.imperva.apiattacktool.activators.EndpointTestRequestDataConverter;
5 | import com.imperva.apiattacktool.activators.TestHttpRequestGenerator;
6 | import com.imperva.apiattacktool.fuzzing.Fuzzer;
7 | import com.imperva.apiattacktool.fuzzing.modelgenerators.CloningIterativeFuzzedModelsGenerator;
8 | import com.imperva.apiattacktool.fuzzing.modelgenerators.SingleValueFuzzedModelsGenerator;
9 | import com.imperva.apiattacktool.fuzzing.parameters.PolicyEnforcer;
10 | import com.imperva.apiattacktool.model.tests.EndpointTestRequestData;
11 | import com.imperva.apiattacktool.model.tests.HttpRequestWrapper;
12 | import com.imperva.apiattacktool.model.tests.NegativeTestHttpResponseValidator;
13 | import com.imperva.apiattacktool.model.valued.EndpointValuedModel;
14 | import com.imperva.apiattacktool.model.valued.factory.PropertyValueFactory;
15 | import com.imperva.apiattacktool.processors.FuzzEndpointModelProcessor;
16 | import com.imperva.apispecparser.model.EndpointModel;
17 |
18 | import java.util.Collections;
19 | import java.util.List;
20 |
21 | public class NegativeSinglePropertyScenarioTestDriver extends AbstractTestDriver implements TestDriver {
22 | private Fuzzer firstStepFuzzer;
23 |
24 | public NegativeSinglePropertyScenarioTestDriver(Fuzzer firstStepFuzzer,
25 | Fuzzer secondStepFuzzer,
26 | PolicyEnforcer policyEnforcer,
27 | PropertyValueFactory propertyValueFactory) {
28 | super(new EndpointModelToValueConverter(propertyValueFactory),
29 | policyEnforcer,
30 | new FuzzEndpointModelProcessor(new SingleValueFuzzedModelsGenerator(propertyValueFactory)),
31 | new FuzzEndpointModelProcessor(new CloningIterativeFuzzedModelsGenerator(propertyValueFactory)),
32 | new EndpointTestRequestDataConverter(),
33 | new TestHttpRequestGenerator(NegativeTestHttpResponseValidator::new),
34 | secondStepFuzzer);
35 | this.firstStepFuzzer = firstStepFuzzer;
36 | }
37 |
38 | @Override
39 | public List getHttpRequestList(String resourceFileName) {
40 | List endpointModelList = parseSwagger(resourceFileName);
41 | if (endpointModelList.isEmpty()) {
42 | return Collections.emptyList();
43 | }
44 |
45 | List endpointValuedModelList = getModelToValueConverter().endpointModelToEndpointValuedModel(endpointModelList);
46 | List modelsWithPolicyEnforced = getPolicyEnforcer().enforcePolicyOn(endpointValuedModelList);
47 | List fuzzedModelsWithPositiveValues = getBeforeMainEndpointModelProcessor().process(modelsWithPolicyEnforced, firstStepFuzzer);
48 | List fuzzedEndpointValuedModelList = getMainEndpointModelProcessor().process(fuzzedModelsWithPositiveValues, getFuzzer());
49 | List endpointTestRequestDataList = getTestRequestDataConverter().processList(fuzzedEndpointValuedModelList);
50 | List httpRequestWrapperList = getHttpRequestGenerator().generateFrom(endpointTestRequestDataList);
51 | return httpRequestWrapperList;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/tests/ScenariosDataProvider.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.tests;
2 |
3 | import com.imperva.apiattacktool.fuzzing.Fuzzer;
4 | import com.imperva.apiattacktool.fuzzing.parameters.AllParametersPolicyEnforcer;
5 | import com.imperva.apiattacktool.fuzzing.parameters.PolicyEnforcer;
6 | import com.imperva.apiattacktool.fuzzing.parameters.RequiredOnlyPolicyEnforcer;
7 | import com.imperva.apiattacktool.fuzzing.value.NegativeSingleValueFuzzer;
8 | import com.imperva.apiattacktool.fuzzing.value.PositiveSingleValueFuzzer;
9 | import com.imperva.apiattacktool.model.tests.HttpRequestWrapper;
10 | import com.imperva.apiattacktool.model.valued.factory.PropertyValueFactory;
11 | import com.imperva.apiattacktool.model.valued.factory.SimplePropertyValueFactory;
12 | import org.slf4j.Logger;
13 | import org.slf4j.LoggerFactory;
14 | import org.testng.ITestContext;
15 | import org.testng.annotations.DataProvider;
16 |
17 | import java.util.List;
18 | import java.util.concurrent.ThreadLocalRandom;
19 |
20 | public class ScenariosDataProvider {
21 | private static final Logger logger = LoggerFactory.getLogger(ScenariosDataProvider.class);
22 |
23 | @DataProvider()
24 | public static Object[][] positiveScenarioDataProvider() {
25 | PropertyValueFactory propertyValueFactory = new SimplePropertyValueFactory();
26 | Fuzzer fuzzer = new PositiveSingleValueFuzzer(propertyValueFactory);
27 | PolicyEnforcer policyEnforcer = new AllParametersPolicyEnforcer();
28 | SingleValueScenarioTestDriver singleValueScenarioTestDriver =
29 | new SingleValueScenarioTestDriver(fuzzer, policyEnforcer, propertyValueFactory);
30 | return getEndpointTestRequestData(singleValueScenarioTestDriver);
31 | }
32 |
33 | @DataProvider()
34 | public static Object[][] positiveRequiredPropertiesOnlyScenarioDataProvider() {
35 | PropertyValueFactory propertyValueFactory = new SimplePropertyValueFactory();
36 | Fuzzer fuzzer = new PositiveSingleValueFuzzer(propertyValueFactory);
37 | PolicyEnforcer policyEnforcer = new RequiredOnlyPolicyEnforcer();
38 | SingleValueScenarioTestDriver singleValueScenarioTestDriver =
39 | new SingleValueScenarioTestDriver(fuzzer, policyEnforcer, propertyValueFactory);
40 | return getEndpointTestRequestData(singleValueScenarioTestDriver);
41 | }
42 |
43 | @DataProvider()
44 | public static Object[][] negativeBadPropertyScenarioDataProvider(ITestContext context) {
45 | PropertyValueFactory propertyValueFactory = new SimplePropertyValueFactory();
46 | PolicyEnforcer policyEnforcer = new AllParametersPolicyEnforcer();
47 | Fuzzer firstStepFuzzer = new PositiveSingleValueFuzzer(propertyValueFactory);
48 | Fuzzer mainStepFuzzer = new NegativeSingleValueFuzzer(propertyValueFactory);
49 | NegativeSinglePropertyScenarioTestDriver negativeSinglePropertyScenarioTestDriver =
50 | new NegativeSinglePropertyScenarioTestDriver(firstStepFuzzer, mainStepFuzzer, policyEnforcer, propertyValueFactory);
51 | return getEndpointTestRequestData(negativeSinglePropertyScenarioTestDriver);
52 | }
53 |
54 | private static Object[][] getEndpointTestRequestData(TestDriver testDriver) {
55 | List httpRequestWrapperList;
56 | try {
57 | httpRequestWrapperList = testDriver.getHttpRequestList(TestConfiguration.getSpecFilePath());
58 | } catch (Exception anyException) {
59 | logger.error("Failed to get httpRequestList, for file: {}", TestConfiguration.getSpecFilePath(), anyException);
60 | return null;
61 | }
62 |
63 | Object[][] result = new Object[httpRequestWrapperList.size()][4];
64 | for (int i = 0; i < httpRequestWrapperList.size(); i++) {
65 | try {
66 | result[i][0] = httpRequestWrapperList.get(i).getHttpRequest();
67 | result[i][1] = httpRequestWrapperList.get(i).getHttpResponseValidator();
68 | result[i][2] = httpRequestWrapperList.get(i).getTestElementComment();
69 | result[i][3] = getTestId();
70 | } catch (Exception anyException) {
71 | logger.error("Error injecting data for test.", anyException);
72 | }
73 | }
74 |
75 | return result;
76 | }
77 |
78 | private static String getTestId() {
79 | return System.currentTimeMillis() + "-" + ThreadLocalRandom.current().nextInt(100000);
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/tests/SingleValueScenarioTestDriver.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.tests;
2 |
3 | import com.imperva.apiattacktool.activators.EndpointModelToValueConverter;
4 | import com.imperva.apiattacktool.activators.EndpointTestRequestDataConverter;
5 | import com.imperva.apiattacktool.activators.TestHttpRequestGenerator;
6 | import com.imperva.apiattacktool.fuzzing.Fuzzer;
7 | import com.imperva.apiattacktool.fuzzing.modelgenerators.SingleValueFuzzedModelsGenerator;
8 | import com.imperva.apiattacktool.fuzzing.parameters.PolicyEnforcer;
9 | import com.imperva.apiattacktool.model.tests.EndpointTestRequestData;
10 | import com.imperva.apiattacktool.model.tests.HttpRequestWrapper;
11 | import com.imperva.apiattacktool.model.tests.PositiveTestHttpResponseValidator;
12 | import com.imperva.apiattacktool.model.valued.EndpointValuedModel;
13 | import com.imperva.apiattacktool.model.valued.factory.PropertyValueFactory;
14 | import com.imperva.apiattacktool.processors.FuzzEndpointModelProcessor;
15 | import com.imperva.apispecparser.model.EndpointModel;
16 |
17 | import java.util.Collections;
18 | import java.util.List;
19 |
20 | public class SingleValueScenarioTestDriver extends AbstractTestDriver implements TestDriver {
21 |
22 | public SingleValueScenarioTestDriver(Fuzzer fuzzer,
23 | PolicyEnforcer policyEnforcer,
24 | PropertyValueFactory propertyValueFactory) {
25 | super(new EndpointModelToValueConverter(propertyValueFactory),
26 | policyEnforcer,
27 | null,
28 | new FuzzEndpointModelProcessor(new SingleValueFuzzedModelsGenerator(propertyValueFactory)),
29 | new EndpointTestRequestDataConverter(),
30 | new TestHttpRequestGenerator(PositiveTestHttpResponseValidator::new),
31 | fuzzer);
32 | }
33 |
34 | @Override
35 | public List getHttpRequestList(String resourceFileName) {
36 | List endpointModelList = parseSwagger(resourceFileName);
37 | if (endpointModelList.isEmpty()) {
38 | return Collections.emptyList();
39 | }
40 |
41 | List endpointValuedModelList = getModelToValueConverter().endpointModelToEndpointValuedModel(endpointModelList);
42 | List modelsWithPolicyEnforced = getPolicyEnforcer().enforcePolicyOn(endpointValuedModelList);
43 | List fuzzedEndpointValuedModelList = getMainEndpointModelProcessor().process(modelsWithPolicyEnforced, getFuzzer());
44 | List endpointTestRequestDataList = getTestRequestDataConverter().processList(fuzzedEndpointValuedModelList);
45 | List httpRequestWrapperList = getHttpRequestGenerator().generateFrom(endpointTestRequestDataList);
46 | return httpRequestWrapperList;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/tests/TestConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.tests;
2 |
3 | import com.imperva.apiattacktool.cli.ApiAttackTool;
4 | import org.apache.commons.lang3.StringUtils;
5 |
6 | import java.util.Collection;
7 | import java.util.Collections;
8 | import java.util.HashSet;
9 | import java.util.List;
10 | import java.util.stream.Collectors;
11 | import java.util.stream.Stream;
12 |
13 | public class TestConfiguration {
14 |
15 | private static final int DEFAULT_PROXY_PORT = 80;
16 | private static final int DEFAULT_HOST_PORT = 443;
17 |
18 | private static String specFilePath = System.getProperty("specFile", null);
19 |
20 | private static String hostScheme = System.getProperty("hostScheme", null);
21 |
22 | private static String hostName = System.getProperty("hostName", null);
23 |
24 | private static Integer hostPort = getIntegerFieldFromProperty("hostPort", DEFAULT_HOST_PORT);
25 |
26 | private static String proxyHost = System.getProperty("proxyHost", null);
27 |
28 | private static Integer proxyPort = getIntegerFieldFromProperty("proxyPort", DEFAULT_PROXY_PORT);
29 |
30 | private static Collection userProvidedPositiveResponseCodes = getIntegerListFromProperty("addPositiveRC", Collections.emptyList());
31 |
32 | private static Collection userProvidedNegativeResponseCodes = getIntegerListFromProperty("addNegativeRC", Collections.emptyList());
33 |
34 | public static void initFrom(ApiAttackTool apiAttackToolOptions) {
35 | specFilePath = apiAttackToolOptions.getSpecFilePath();
36 | hostScheme = apiAttackToolOptions.getHostScheme();
37 | hostName = apiAttackToolOptions.getHostName();
38 | hostPort = apiAttackToolOptions.getHostPort();
39 | proxyHost = apiAttackToolOptions.getProxyHost();
40 | proxyPort = apiAttackToolOptions.getProxyPort();
41 | userProvidedPositiveResponseCodes =
42 | apiAttackToolOptions.getUserProvidedPositiveResponseCodes() == null
43 | ? Collections.emptyList()
44 | : new HashSet<>(apiAttackToolOptions.getUserProvidedPositiveResponseCodes());
45 | userProvidedNegativeResponseCodes =
46 | apiAttackToolOptions.getUserProvidedNegativeResponseCodes() == null
47 | ? Collections.emptyList()
48 | : new HashSet<>(apiAttackToolOptions.getUserProvidedNegativeResponseCodes());
49 | }
50 |
51 | public static String getSpecFilePath() {
52 | return specFilePath;
53 | }
54 |
55 | public static String getHostScheme() {
56 | return hostScheme;
57 | }
58 |
59 | public static String getHostName() {
60 | return hostName;
61 | }
62 |
63 | public static int getHostPort() {
64 | return hostPort == null ? DEFAULT_HOST_PORT : hostPort;
65 | }
66 |
67 | public static String getProxyHost() {
68 | return proxyHost;
69 | }
70 |
71 | public static int getProxyPort() {
72 | return proxyPort == null ? DEFAULT_PROXY_PORT : proxyPort;
73 | }
74 |
75 | public static boolean isProxyDefined() {
76 | return !StringUtils.isBlank(proxyHost);
77 | }
78 |
79 | public static Collection getUserProvidedPositiveResponseCodes() {
80 | return userProvidedPositiveResponseCodes;
81 | }
82 |
83 | public static Collection getUserProvidedNegativeResponseCodes() {
84 | return userProvidedNegativeResponseCodes;
85 | }
86 |
87 | public static String getWorkingConfigurationString() {
88 | return "API Spec file path: " + specFilePath + "\n"
89 | + "Host: (" + hostScheme + ") " + hostName + " : " + getHostPort() + "\n"
90 | + (isProxyDefined()
91 | ? "Proxy Host: " + proxyHost + " : " + getProxyPort() + "\n"
92 | : "");
93 |
94 | }
95 |
96 | private static Integer getIntegerFieldFromProperty(String propertyName, Integer defaultValue) {
97 | String propertyValue = System.getProperty(propertyName);
98 | if (StringUtils.isBlank(propertyValue)) {
99 | return defaultValue;
100 | }
101 |
102 | return Integer.parseInt(propertyValue);
103 | }
104 |
105 | private static Collection getIntegerListFromProperty(String propertyName, List defaultValue) {
106 | String propertyValue = System.getProperty(propertyName);
107 | if (StringUtils.isBlank(propertyValue)) {
108 | return defaultValue;
109 | }
110 |
111 | String[] listValues = propertyValue.split("[,]");
112 | Collection integerCollection =
113 | Stream.of(listValues).map(Integer::parseInt).collect(Collectors.toCollection(HashSet::new));
114 | return integerCollection;
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/tests/TestDriver.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.tests;
2 |
3 | import com.imperva.apiattacktool.model.tests.HttpRequestWrapper;
4 |
5 | import java.util.List;
6 |
7 | public interface TestDriver {
8 | List getHttpRequestList(String resourceFileName);
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/tests/TestHttpResponse.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.tests;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 |
5 | public class TestHttpResponse {
6 | private String incidentId;
7 | @JsonProperty("hostName")
8 | private String hostname;
9 | private String errorCode;
10 | @JsonProperty("description")
11 | private String responseDescription;
12 | private String timeUtc;
13 | private String clientIp;
14 | private String proxyId;
15 | private String proxyIp;
16 |
17 | public String getIncidentId() {
18 | return incidentId;
19 | }
20 |
21 | public void setIncidentId(String incidentId) {
22 | this.incidentId = incidentId;
23 | }
24 |
25 | public String getHostname() {
26 | return hostname;
27 | }
28 |
29 | public void setHostname(String hostname) {
30 | this.hostname = hostname;
31 | }
32 |
33 | public String getErrorCode() {
34 | return errorCode;
35 | }
36 |
37 | public void setErrorCode(String errorCode) {
38 | this.errorCode = errorCode;
39 | }
40 |
41 | public String getResponseDescription() {
42 | return responseDescription;
43 | }
44 |
45 | public void setResponseDescription(String responseDescription) {
46 | this.responseDescription = responseDescription;
47 | }
48 |
49 | public String getTimeUtc() {
50 | return timeUtc;
51 | }
52 |
53 | public void setTimeUtc(String timeUtc) {
54 | this.timeUtc = timeUtc;
55 | }
56 |
57 | public String getClientIp() {
58 | return clientIp;
59 | }
60 |
61 | public void setClientIp(String clientIp) {
62 | this.clientIp = clientIp;
63 | }
64 |
65 | public String getProxyId() {
66 | return proxyId;
67 | }
68 |
69 | public void setProxyId(String proxyId) {
70 | this.proxyId = proxyId;
71 | }
72 |
73 | public String getProxyIp() {
74 | return proxyIp;
75 | }
76 |
77 | public void setProxyIp(String proxyIp) {
78 | this.proxyIp = proxyIp;
79 | }
80 |
81 | @Override
82 | public String toString() {
83 | return "TestHttpResponse{\n"
84 | + "\tincidentId :'" + incidentId + "\'\n"
85 | + "\thostname :'" + hostname + "\'\n"
86 | + "\terrorCode :'" + errorCode + "\'\n"
87 | + "\tresponseDescription :'" + responseDescription + "\'\n"
88 | + "\ttimeUtc :'" + timeUtc + "\'\n"
89 | + "\tclientIp :'" + clientIp + "\'\n"
90 | + "\tproxyId :'" + proxyId + "'\'\n"
91 | + "\tproxyIp :'" + proxyIp + "\'\n"
92 | + '}';
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apiattacktool/utils/TestReporter.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apiattacktool.utils;
2 |
3 | import org.testng.Reporter;
4 |
5 | public class TestReporter {
6 |
7 | public static void log(Object message) {
8 | log(String.valueOf(message));
9 | }
10 |
11 | public static void log(String message) {
12 | Reporter.log(message, true);
13 | }
14 |
15 | public static void log(Exception exception) {
16 | Throwable currentException = exception;
17 | int i = 0;
18 | do {
19 | Reporter.log((i > 0 ? "at " : "") + currentException.getMessage(), true);
20 | currentException = currentException.getCause();
21 | i++;
22 | } while (currentException != null);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/exceptions/ParseException.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.exceptions;
2 |
3 | public class ParseException extends Exception {
4 | public ParseException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/model/ArrayProperty.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.model;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | public class ArrayProperty extends Property {
7 | private Boolean areItemsUnique;
8 | private PropertyNode items;
9 | private int minimumItems;
10 | private Integer maximumItems;
11 | private CollectionFormat collectionFormat;
12 |
13 | public ArrayProperty(Property property, Boolean areItemsUnique, PropertyNode items, Integer minItems, Integer maxItems, String collectionFormat) {
14 | super(property);
15 | this.areItemsUnique = areItemsUnique;
16 | this.items = items;
17 | this.minimumItems = minItems == null ? 0 : minItems;
18 | this.maximumItems = maxItems;
19 | this.collectionFormat = CollectionFormat.getBySpecCollectionFormat(collectionFormat); // Sets CSV as default
20 | }
21 |
22 | public Boolean getAreItemsUnique() {
23 | return areItemsUnique;
24 | }
25 |
26 | public PropertyNode getItems() {
27 | return items;
28 | }
29 |
30 | public int getMinimumItems() {
31 | return minimumItems;
32 | }
33 |
34 | public Integer getMaximumItems() {
35 | return maximumItems;
36 | }
37 |
38 | public CollectionFormat getCollectionFormat() {
39 | return collectionFormat;
40 | }
41 |
42 | @Override
43 | public String toString() {
44 | return "ArrayProperty{"
45 | + "areItemsUnique=" + areItemsUnique
46 | + ", items=" + items
47 | + ", minimumItems=" + minimumItems
48 | + ", maximumItems=" + maximumItems
49 | + ", Property=" + super.toString()
50 | + '}';
51 | }
52 |
53 | public enum CollectionFormat {
54 | COMMA_SEPARATED_VALUES("csv", ","),
55 | SPACE_SEPARATED_VALUES("ssv", "\\s"),
56 | TAB_SEPARATED_VALUES("tsv", "\\t"),
57 | PIPE_SEPARATED_VALUES("pipes", "\\|"),
58 | AMPERSAND_CONCATENATED_VALUES("multi", "&");
59 |
60 | private static final Map enumValuesMap = initializeMapping();
61 | private String formatString;
62 | private String outputString;
63 |
64 | CollectionFormat(String formatString, String outputString) {
65 | this.formatString = formatString;
66 | this.outputString = outputString;
67 | }
68 |
69 | private static Map initializeMapping() {
70 | Map enumValuesMap = new HashMap<>();
71 | for (CollectionFormat collectionFormat : CollectionFormat.values()) {
72 | enumValuesMap.put(collectionFormat.formatString, collectionFormat);
73 | }
74 | return enumValuesMap;
75 | }
76 |
77 | public static CollectionFormat getBySpecCollectionFormat(String specFormat) {
78 | CollectionFormat collectionFormat = enumValuesMap.get(specFormat);
79 | if (collectionFormat == null) {
80 | collectionFormat = COMMA_SEPARATED_VALUES;
81 | }
82 | return collectionFormat;
83 | }
84 |
85 | public String getFormatString() {
86 | return formatString;
87 | }
88 |
89 | public String getOutputString() {
90 | return outputString;
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/model/BooleanProperty.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.model;
2 |
3 | import java.util.List;
4 |
5 | public class BooleanProperty extends EnumerableProperty {
6 | public BooleanProperty(Property property, List enumList) {
7 | super(property, enumList);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/model/EndpointModel.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.model;
2 |
3 | import com.imperva.apiattacktool.model.tests.HttpMethod;
4 |
5 | import java.util.Collections;
6 | import java.util.LinkedList;
7 | import java.util.List;
8 | import java.util.Map;
9 |
10 | public class EndpointModel {
11 |
12 | private String fullPathWithParamBrackets;
13 | private HttpMethod httpMethod;
14 | private List consumes;
15 | private PropertyNode propertiesNode;
16 | private List httpResponseCodesList;
17 |
18 | public EndpointModel(String fullPathWithParamBrackets, HttpMethod httpMethod, List consumes) {
19 | this.fullPathWithParamBrackets = fullPathWithParamBrackets;
20 | this.httpMethod = httpMethod;
21 | this.consumes = consumes == null ? Collections.emptyList() : consumes;
22 | this.propertiesNode = new PropertyNode(null, false, null);
23 | this.httpResponseCodesList = new LinkedList<>();
24 | }
25 |
26 | public void addParameter(String name, Property property) {
27 | propertiesNode.getPropertiesMap().put(name, property);
28 | }
29 |
30 | public void addNode(String name, PropertyNode propertyNode) {
31 | propertiesNode.getChildrenMap().put(name, propertyNode);
32 | }
33 |
34 | public void addResponseCode(int responseCode) {
35 | this.httpResponseCodesList.add(responseCode);
36 | }
37 |
38 | public Map getSimpleParametersMap() {
39 | return propertiesNode.getPropertiesMap();
40 | }
41 |
42 | public String getFullPathWithParamBrackets() {
43 | return fullPathWithParamBrackets;
44 | }
45 |
46 | public HttpMethod getHttpMethod() {
47 | return httpMethod;
48 | }
49 |
50 | public List getConsumes() {
51 | return consumes;
52 | }
53 |
54 | public Map getChildrenMap() {
55 | return propertiesNode.getChildrenMap();
56 | }
57 |
58 | public List getHttpResponseCodesList() {
59 | return httpResponseCodesList;
60 | }
61 |
62 | public String toString() {
63 | return String.format("Endpoint: %s %s%nNodes:%n%s%nValues:%n%s",
64 | httpMethod, fullPathWithParamBrackets, propertiesNode.getChildrenMap(), propertiesNode.getPropertiesMap());
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/model/EnumerableProperty.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.model;
2 |
3 | import java.util.List;
4 |
5 | public class EnumerableProperty extends Property {
6 |
7 | private List enumList;
8 |
9 | public EnumerableProperty(Property property, List enumList) {
10 | super(property);
11 | this.enumList = enumList;
12 | }
13 |
14 | public List getEnumList() {
15 | return enumList;
16 | }
17 |
18 | @Override
19 | public String toString() {
20 | return "{"
21 | + "enumList=" + enumList
22 | + ", Property=" + super.toString() + '}';
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/model/NumericProperty.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.model;
2 |
3 | import java.math.BigDecimal;
4 | import java.util.List;
5 |
6 | public class NumericProperty extends EnumerableProperty {
7 | private BigDecimal minimum;
8 | private BigDecimal maximum;
9 | private Number multipleOf;
10 | private boolean exclusiveMinimum;
11 | private boolean exclusiveMaximum;
12 |
13 | public NumericProperty(Property property, List enumList,
14 | BigDecimal minimum, BigDecimal maximum, Number multipleOf, Boolean exclusiveMinimum,
15 | Boolean exclusiveMaximum) {
16 | super(property, enumList);
17 | this.minimum = minimum;
18 | this.maximum = maximum;
19 | this.multipleOf = multipleOf;
20 | this.exclusiveMinimum = exclusiveMinimum != null && exclusiveMinimum;
21 | this.exclusiveMaximum = exclusiveMaximum != null && exclusiveMaximum;
22 | }
23 |
24 | public BigDecimal getMinimum() {
25 | return minimum;
26 | }
27 |
28 | public BigDecimal getMaximum() {
29 | return maximum;
30 | }
31 |
32 | public Number getMultipleOf() {
33 | return multipleOf;
34 | }
35 |
36 | public boolean getExclusiveMinimum() {
37 | return exclusiveMinimum;
38 | }
39 |
40 | public boolean getExclusiveMaximum() {
41 | return exclusiveMaximum;
42 | }
43 |
44 | @Override
45 | public Object clone() throws CloneNotSupportedException {
46 | return super.clone();
47 | }
48 |
49 | @Override
50 | public String toString() {
51 | return "NumericProperty{"
52 | + "minimum=" + minimum
53 | + ", maximum=" + maximum
54 | + ", multipleOf=" + multipleOf
55 | + ", exclusiveMinimum=" + exclusiveMinimum
56 | + ", exclusiveMaximum=" + exclusiveMaximum
57 | + ", EnumerableProperty=" + super.toString() + '}';
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/model/Property.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.model;
2 |
3 | import com.imperva.apiattacktool.model.tests.ParameterLocation;
4 |
5 | public class Property implements Cloneable {
6 | private ParameterLocation location;
7 | private PropertyType type;
8 | private String name;
9 | private boolean isRequired;
10 |
11 | /**
12 | * Relevant only for Schema "properties" definitions. Declares the property as "read only".
13 | * This means that it MAY be sent as part of a response but MUST NOT be sent as part of the request.
14 | */
15 | private boolean isReadOnly;
16 |
17 | /**
18 | * Valid only for either query or formData parameters and allows you to send a parameter with a name only or an empty value.
19 | * Default value is false
20 | */
21 | private boolean allowEmptyValue;
22 |
23 | public Property(ParameterLocation location, PropertyType type, String name, boolean isRequired, Boolean isReadOnly, Boolean allowEmptyValue) {
24 | this.location = location;
25 | this.type = type;
26 | this.name = name;
27 | this.isRequired = isRequired;
28 | this.isReadOnly = isReadOnly != null && isReadOnly;
29 | this.allowEmptyValue = allowEmptyValue != null && allowEmptyValue;
30 | }
31 |
32 | public Property(Property otherProperty) {
33 | this.location = otherProperty.getParameterLocation();
34 | this.type = otherProperty.getType();
35 | this.name = otherProperty.getName();
36 | this.isRequired = otherProperty.isRequired();
37 | this.isReadOnly = otherProperty.getReadOnly();
38 | this.allowEmptyValue = otherProperty.getAllowEmptyValue();
39 | }
40 |
41 | @Override
42 | public Object clone() throws CloneNotSupportedException {
43 | return super.clone();
44 | }
45 |
46 | public ParameterLocation getParameterLocation() {
47 | return location;
48 | }
49 |
50 | public PropertyType getType() {
51 | return type;
52 | }
53 |
54 | public String getName() {
55 | return name;
56 | }
57 |
58 | public boolean isRequired() {
59 | return isRequired;
60 | }
61 |
62 | public boolean getReadOnly() {
63 | return isReadOnly;
64 | }
65 |
66 | public boolean getAllowEmptyValue() {
67 | return allowEmptyValue;
68 | }
69 |
70 | @Override
71 | public String toString() {
72 | return "{"
73 | + "location=" + location
74 | + ",type='" + type + '\''
75 | + ",name='" + name + '\''
76 | + ", isRequired='" + isRequired + '\''
77 | + '}';
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/model/PropertyNode.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.model;
2 |
3 | import com.imperva.apiattacktool.model.tests.ParameterLocation;
4 |
5 | import java.util.HashMap;
6 | import java.util.Map;
7 |
8 | public class PropertyNode {
9 |
10 | private String name;
11 | private boolean isRequired;
12 |
13 | private ParameterLocation parameterLocation;
14 | private Map propertyNameToPropertyValueMap;
15 | private Map propertyNameToPropertyNodeMap;
16 |
17 | public PropertyNode(String name, boolean isRequired, ParameterLocation parameterLocation) {
18 | this.name = name;
19 | this.isRequired = isRequired;
20 | this.parameterLocation = parameterLocation;
21 | this.propertyNameToPropertyNodeMap = new HashMap<>();
22 | this.propertyNameToPropertyValueMap = new HashMap<>();
23 | }
24 |
25 | public String getName() {
26 | return name;
27 | }
28 |
29 | public boolean isRequired() {
30 | return isRequired;
31 | }
32 |
33 | public void addPropertyValueType(String propertyName, Property property) {
34 | propertyNameToPropertyValueMap.put(propertyName, property);
35 | }
36 |
37 | public void addPropertyNode(String propertyName, PropertyNode propertyNode) {
38 | propertyNameToPropertyNodeMap.put(propertyName, propertyNode);
39 | }
40 |
41 | public ParameterLocation getParameterLocation() {
42 | return parameterLocation;
43 | }
44 |
45 | public Map getPropertiesMap() {
46 | return propertyNameToPropertyValueMap;
47 | }
48 |
49 | public boolean hasChildren() {
50 | return propertyNameToPropertyNodeMap.size() > 0;
51 | }
52 |
53 | public Map getChildrenMap() {
54 | return propertyNameToPropertyNodeMap;
55 | }
56 |
57 | @Override
58 | public String toString() {
59 | return "{location='" + parameterLocation + '\''
60 | + ", properties='" + propertyNameToPropertyValueMap.toString() + '\''
61 | + ", children='" + propertyNameToPropertyNodeMap + '\'' + "}";
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/model/PropertyType.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.model;
2 |
3 | import com.imperva.apiattacktool.infra.Tuple;
4 |
5 | import java.util.Collections;
6 | import java.util.HashMap;
7 | import java.util.Map;
8 |
9 | public enum PropertyType {
10 | ARRAY("array", "null", null),
11 | BOOLEAN("boolean", "null", Boolean.class),
12 | BASE_INTEGER("integer", "null", Integer.class),
13 | INTEGER("integer", "int32", Integer.class),
14 | LONG("integer", "int64", Long.class),
15 | DECIMAL("number", "null", Double.class), // This also accepts custom formats
16 | DOUBLE("number", "double", Double.class),
17 | FLOAT("number", "float", Float.class),
18 | BINARY("string", "binary", String.class),
19 | BYTE_ARRAY("string", "byte", String.class),
20 | DATE("string", "date", String.class),
21 | DATETIME("string", "date-time", String.class),
22 | EMAIL("string", "email", String.class),
23 | PASSWORD("string", "password", String.class),
24 | UUID("string", "uuid", String.class),
25 | STRING("string", "null", String.class),
26 | FILE("file", "null", null),
27 | UNTYPED("null", "null", null);
28 |
29 | private String type;
30 | private String format;
31 | private Class castingClass;
32 | private static final Map, PropertyType> enumValuesMap = Collections.unmodifiableMap(initializeMapping());
33 |
34 | PropertyType(String type, String format, Class clazz) {
35 | this.type = type;
36 | this.format = format;
37 | this.castingClass = clazz;
38 | }
39 |
40 | public static PropertyType getValueByTypeAndFormat(String type, String format) {
41 | if (type == null) {
42 | type = "null";
43 | }
44 | if (format == null) {
45 | format = "null";
46 | }
47 |
48 | if ("number".equals(type) && !"double".equals(format) && !"float".equals(format)) {
49 | return DECIMAL;
50 | }
51 | return enumValuesMap.get(new Tuple<>(type, format));
52 | }
53 |
54 | private static Map, PropertyType> initializeMapping() {
55 | Map, PropertyType> enumValuesMap = new HashMap<>();
56 | for (PropertyType propertyType : PropertyType.values()) {
57 | enumValuesMap.put(new Tuple<>(propertyType.type, propertyType.format), propertyType);
58 | }
59 | return enumValuesMap;
60 | }
61 |
62 | public Class getCastingClass() {
63 | return castingClass;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/model/StringProperty.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.model;
2 |
3 | import java.util.List;
4 |
5 | public class StringProperty extends EnumerableProperty {
6 | private int minLength;
7 | private Integer maxLength;
8 | private String pattern;
9 |
10 | public StringProperty(Property property, List enumList,
11 | Integer minLength, Integer maxLength, String pattern) {
12 | super(property, enumList);
13 | this.minLength = minLength == null ? 0 : minLength;
14 | this.maxLength = maxLength;
15 | this.pattern = pattern;
16 | }
17 |
18 | public int getMinLength() {
19 | return minLength;
20 | }
21 |
22 | public Integer getMaxLength() {
23 | return maxLength;
24 | }
25 |
26 | public String getPattern() {
27 | return pattern;
28 | }
29 |
30 | @Override
31 | public String toString() {
32 | return "StringProperty{"
33 | + "minLength=" + minLength
34 | + ", maxLength=" + maxLength
35 | + ", pattern='" + pattern + '\''
36 | + ", EnumerableProperty= " + super.toString() + '}';
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/normalizer/ApiDefinitions.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.normalizer;
2 |
3 | import java.util.Map;
4 |
5 | public interface ApiDefinitions {
6 |
7 | Map getDefinitions();
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/normalizer/NormalizedApiSpec.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.normalizer;
2 |
3 | import java.util.Map;
4 |
5 | public interface NormalizedApiSpec {
6 |
7 | Map getPathHashCodeToNormalizedPathMap();
8 |
9 | void addNormalizedPath(Integer pathHashCode, NormalizedPath normalizedPath);
10 |
11 | NormalizedPath getNormalizedPath(Integer pathHashCode);
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/normalizer/NormalizedApiSpecImpl.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.normalizer;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | public abstract class NormalizedApiSpecImpl implements NormalizedApiSpec {
7 |
8 | private Map pathHashCodeToNormalizedPathMap = new HashMap<>();
9 |
10 | @Override
11 | public Map getPathHashCodeToNormalizedPathMap() {
12 | return pathHashCodeToNormalizedPathMap;
13 | }
14 |
15 | @Override
16 | public void addNormalizedPath(Integer pathHashCode, NormalizedPath normalizedPath) {
17 | pathHashCodeToNormalizedPathMap.put(pathHashCode, normalizedPath);
18 | }
19 |
20 | @Override
21 | public NormalizedPath getNormalizedPath(Integer pathHashCode) {
22 | return pathHashCodeToNormalizedPathMap.get(pathHashCode);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/normalizer/NormalizedEndpoint.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.normalizer;
2 |
3 | import java.util.Map;
4 |
5 | public interface NormalizedEndpoint {
6 |
7 | String getName();
8 |
9 | Map getNormalizedParametersMap();
10 |
11 | void addNormalizedParameter(Integer parameterHashCode, NormalizedParameter normalizedParameter);
12 |
13 | NormalizedParameter getNormalizedParameter(Integer parameterHashCode);
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/normalizer/NormalizedEndpointImpl.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.normalizer;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | public abstract class NormalizedEndpointImpl implements NormalizedEndpoint {
7 |
8 | private final String name;
9 | private Map parameterHashCodeToNormalizedParameterMap = new HashMap<>();
10 |
11 | public NormalizedEndpointImpl(String name) {
12 | this.name = name;
13 | }
14 |
15 | @Override
16 | public String getName() {
17 | return name;
18 | }
19 |
20 | @Override
21 | public Map getNormalizedParametersMap() {
22 | return parameterHashCodeToNormalizedParameterMap;
23 | }
24 |
25 | @Override
26 | public void addNormalizedParameter(Integer parameterHashCode, NormalizedParameter normalizedParameter) {
27 | parameterHashCodeToNormalizedParameterMap.put(parameterHashCode, normalizedParameter);
28 | }
29 |
30 | @Override
31 | public NormalizedParameter getNormalizedParameter(Integer parameterHashCode) {
32 | if (parameterHashCodeToNormalizedParameterMap == null) {
33 | return null;
34 | }
35 |
36 | return parameterHashCodeToNormalizedParameterMap.get(parameterHashCode);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/normalizer/NormalizedParameter.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.normalizer;
2 |
3 | public interface NormalizedParameter {
4 |
5 | ApiDefinitions getApiDefinitions();
6 |
7 | int getTotalPropertiesCount();
8 |
9 | T getParameter();
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/normalizer/NormalizedPath.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.normalizer;
2 |
3 | import java.util.Map;
4 |
5 | public interface NormalizedPath {
6 |
7 | Map getNormalizedEndpointsMap();
8 |
9 | void addNormalizedEndpoint(Integer endpointHashCode, NormalizedEndpoint normalizedEndpoint);
10 |
11 | NormalizedEndpoint getNormalizedEndpoint(Integer endpointHashCode);
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/normalizer/NormalizedPathImpl.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.normalizer;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | public abstract class NormalizedPathImpl implements NormalizedPath {
7 |
8 | private Map endpointHashCodeToNormalizedParameterMap = new HashMap<>();
9 |
10 | @Override
11 | public Map getNormalizedEndpointsMap() {
12 | return endpointHashCodeToNormalizedParameterMap;
13 | }
14 |
15 | @Override
16 | public void addNormalizedEndpoint(Integer endpointHashCode, NormalizedEndpoint normalizedEndpoint) {
17 | endpointHashCodeToNormalizedParameterMap.put(endpointHashCode, normalizedEndpoint);
18 | }
19 |
20 | @Override
21 | public NormalizedEndpoint getNormalizedEndpoint(Integer endpointHashCode) {
22 | return endpointHashCodeToNormalizedParameterMap == null ? null : endpointHashCodeToNormalizedParameterMap.get(endpointHashCode);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/normalizer/swagger/SwaggerDefinitions.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.normalizer.swagger;
2 |
3 | import com.imperva.apispecparser.normalizer.ApiDefinitions;
4 | import io.swagger.models.Model;
5 |
6 | import java.util.HashMap;
7 | import java.util.Map;
8 |
9 | public class SwaggerDefinitions implements ApiDefinitions {
10 |
11 | private Map definitions;
12 |
13 | public SwaggerDefinitions(Map definitions) {
14 | this.definitions = definitions;
15 | }
16 |
17 | @Override
18 | public Map getDefinitions() {
19 | return definitions;
20 | }
21 |
22 | public void addDefinition(String modelName, Model model) {
23 | if (definitions == null) {
24 | definitions = new HashMap<>();
25 | }
26 |
27 | definitions.put(getSimpleModelName(modelName), model);
28 | }
29 |
30 | public void removeDefinition(String modelName) {
31 | if (definitions != null) {
32 | definitions.remove(modelName);
33 | }
34 | }
35 |
36 | public Model getDefinition(String modelName) {
37 | if (definitions == null || modelName == null) {
38 | return null;
39 | }
40 |
41 | return definitions.get(getSimpleModelName(modelName));
42 | }
43 |
44 | public boolean containsDefinition(String modelName) {
45 | return definitions != null && definitions.get(modelName) != null;
46 | }
47 |
48 | private String getSimpleModelName(String modelName) {
49 | return modelName == null ? null : modelName.substring(modelName.lastIndexOf("/") + 1);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/normalizer/swagger/SwaggerDefinitionsNormalizer.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.normalizer.swagger;
2 |
3 | import io.swagger.models.Model;
4 | import io.swagger.models.ModelImpl;
5 | import io.swagger.models.RefModel;
6 | import io.swagger.models.parameters.BodyParameter;
7 | import io.swagger.models.parameters.Parameter;
8 | import io.swagger.models.properties.ArrayProperty;
9 | import io.swagger.models.properties.Property;
10 | import io.swagger.models.properties.RefProperty;
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 |
14 | import java.util.HashSet;
15 | import java.util.Map;
16 | import java.util.Set;
17 |
18 | public class SwaggerDefinitionsNormalizer {
19 |
20 | private static Logger logger = LoggerFactory.getLogger(SwaggerDefinitionsNormalizer.class);
21 |
22 | public static SwaggerNormalizedParameter normalizeParameterDefinitions(Parameter parameter,
23 | Map swaggerFullDefinitions) {
24 | SwaggerNormalizedParameter swaggerDefinitionNormalizerResult;
25 |
26 | if (parameter instanceof BodyParameter) {
27 | BodyParameter bodyParameter = (BodyParameter) parameter;
28 | Model model = bodyParameter.getSchema();
29 | swaggerDefinitionNormalizerResult = SwaggerDefinitionsNormalizer.normalizeModelDefinitions(null, model, null, "",
30 | swaggerFullDefinitions, new HashSet<>(), new SwaggerNormalizedParameter<>(parameter));
31 | } else {
32 | swaggerDefinitionNormalizerResult = new SwaggerNormalizedParameter<>(parameter, swaggerFullDefinitions, 1);
33 | }
34 |
35 | return swaggerDefinitionNormalizerResult;
36 | }
37 |
38 | private static SwaggerNormalizedParameter normalizeModelDefinitions(String currentModelName, Model currentModel, Model parentModel, String ref,
39 | Map swaggerFullDefinitions, Set scannedModels,
40 | SwaggerNormalizedParameter swaggerDefinitionNormalizerResult) {
41 |
42 | Model filteredModel = null;
43 |
44 | if (swaggerDefinitionNormalizerResult.containsDefinition(currentModelName)) {
45 | filteredModel = swaggerDefinitionNormalizerResult.getDefinition(currentModelName);
46 | } else if (currentModel != null) {
47 | filteredModel = (Model) currentModel.clone();
48 |
49 | if (currentModelName != null) {
50 | swaggerDefinitionNormalizerResult.addDefinition(currentModelName, filteredModel);
51 | }
52 | }
53 |
54 | if (filteredModel instanceof RefModel) {
55 | RefModel refModel = (RefModel) currentModel;
56 | String definitionName = refModel.getSimpleRef();
57 | Model definitionModel = swaggerFullDefinitions.get(definitionName);
58 | Model newParentModel = parentModel == null ? null : currentModel; //parentModel will be null only on first iteration
59 |
60 | //Remove Ref model (definition) that point to itself
61 | if (definitionModel == currentModel) {
62 | swaggerDefinitionNormalizerResult.removeDefinition(currentModelName);
63 | return swaggerDefinitionNormalizerResult;
64 | }
65 |
66 | normalizeModelDefinitions(definitionName, definitionModel, newParentModel, ref + "/" + definitionName, swaggerFullDefinitions,
67 | scannedModels, swaggerDefinitionNormalizerResult);
68 | } else if (filteredModel instanceof ModelImpl) {
69 | ModelImpl currentModelImpl = (ModelImpl) currentModel;
70 | ModelImpl filteredModelImpl = (ModelImpl) filteredModel;
71 |
72 | //Workaround to bug in swagger model clone which ignore some fields
73 | filteredModelImpl._enum(currentModelImpl.getEnum());
74 | filteredModelImpl.format(currentModelImpl.getFormat());
75 | filteredModelImpl.allowEmptyValue(currentModelImpl.getAllowEmptyValue());
76 | filteredModelImpl.uniqueItems(currentModelImpl.getUniqueItems());
77 |
78 |
79 | Map propertyMap = currentModelImpl.getProperties();
80 |
81 | if (propertyMap != null) {
82 | for (String propertyName : currentModelImpl.getProperties().keySet()) {
83 | Property property = currentModelImpl.getProperties().get(propertyName);
84 |
85 | Set propertyScannedModels;
86 |
87 | //If parent model is null this means we're dealing with a new property (not part of the recursion)
88 | //In this case, the 'scannedModels' should be initiated (every single property should calculate loop in its own tree)
89 | if (parentModel == null) {
90 | propertyScannedModels = new HashSet<>();
91 | } else {
92 | propertyScannedModels = scannedModels;
93 | }
94 |
95 | propertyScannedModels.add(currentModelName);
96 |
97 | filterProperty(currentModelName, filteredModel, property, propertyName, ref, swaggerFullDefinitions, propertyScannedModels,
98 | swaggerDefinitionNormalizerResult);
99 | }
100 | }
101 | }
102 |
103 | return swaggerDefinitionNormalizerResult;
104 | }
105 |
106 | private static void filterProperty(String parentModelName, Model parentFilteredModel, Property property, String propertyName, String ref,
107 | Map swaggerFullDefinitions, Set scannedModels,
108 | SwaggerNormalizedParameter swaggerDefinitionNormalizerResult) {
109 |
110 | if (property instanceof RefProperty) {
111 | RefProperty refProperty = (RefProperty) property;
112 | String refPropertyName = refProperty.getSimpleRef();
113 | Model definitionModel = swaggerFullDefinitions.get(refPropertyName);
114 |
115 | String propertyRef = ref + " -> " + refPropertyName + " (" + propertyName + ")";
116 |
117 | if (scannedModels.contains(refPropertyName)) {
118 | if (parentFilteredModel.getProperties().containsKey(propertyName)) {
119 | logger.info("Removing circular property [{}] from Model [{}], Ref: {}", propertyName, parentModelName, propertyRef);
120 | parentFilteredModel.getProperties().remove(propertyName);
121 | }
122 | } else {
123 | normalizeModelDefinitions(refPropertyName, definitionModel, parentFilteredModel, propertyRef, swaggerFullDefinitions, scannedModels,
124 | swaggerDefinitionNormalizerResult);
125 | }
126 |
127 | } else if (property instanceof ArrayProperty) {
128 | ArrayProperty arrayProperty = (ArrayProperty) property;
129 | filterProperty(parentModelName, parentFilteredModel, arrayProperty.getItems(), propertyName, ref, swaggerFullDefinitions, scannedModels,
130 | swaggerDefinitionNormalizerResult);
131 | } else {
132 | swaggerDefinitionNormalizerResult.incrementTotalPropertiesCount();
133 | }
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/normalizer/swagger/SwaggerNormalizedApiSpec.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.normalizer.swagger;
2 |
3 | import com.imperva.apispecparser.normalizer.NormalizedApiSpecImpl;
4 | import com.imperva.apispecparser.normalizer.NormalizedPath;
5 | import io.swagger.models.Path;
6 |
7 | public class SwaggerNormalizedApiSpec extends NormalizedApiSpecImpl {
8 |
9 | public void addNormalizedPath(Path path, SwaggerNormalizedPath swaggerNormalizedPath) {
10 | if (path != null) {
11 | addNormalizedPath(path.hashCode(), swaggerNormalizedPath);
12 | }
13 | }
14 |
15 | public SwaggerNormalizedPath getNormalizedPath(Path path) {
16 | if (path != null) {
17 | return getNormalizedPath(path.hashCode());
18 | }
19 |
20 | return null;
21 | }
22 |
23 | @Override
24 | public SwaggerNormalizedPath getNormalizedPath(Integer pathHashCode) {
25 | NormalizedPath normalizedPath = super.getNormalizedPath(pathHashCode);
26 | return normalizedPath == null ? null : (SwaggerNormalizedPath) normalizedPath;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/normalizer/swagger/SwaggerNormalizedEndpoint.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.normalizer.swagger;
2 |
3 | import com.imperva.apispecparser.normalizer.NormalizedEndpointImpl;
4 | import com.imperva.apispecparser.normalizer.NormalizedParameter;
5 | import io.swagger.models.Operation;
6 | import io.swagger.models.Path;
7 | import io.swagger.models.parameters.Parameter;
8 |
9 | public class SwaggerNormalizedEndpoint extends NormalizedEndpointImpl {
10 |
11 | private final Path path;
12 | private final Operation operation;
13 |
14 | public SwaggerNormalizedEndpoint(String endpointName, Path path, Operation operation) {
15 | super(endpointName);
16 | this.path = path;
17 | this.operation = operation;
18 | }
19 |
20 | public void addNormalizedParameter(Parameter parameter, SwaggerNormalizedParameter normalizedParameter) {
21 | if (path != null && operation != null && parameter != null) {
22 | addNormalizedParameter(parameter.hashCode(), normalizedParameter);
23 | }
24 | }
25 |
26 | public SwaggerNormalizedParameter getNormalizedParameter(Parameter parameter) {
27 | if (parameter == null) {
28 | return null;
29 | }
30 |
31 | NormalizedParameter normalizedParameter = super.getNormalizedParameter(parameter.hashCode());
32 | return normalizedParameter == null ? null : (SwaggerNormalizedParameter) normalizedParameter;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/normalizer/swagger/SwaggerNormalizedParameter.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.normalizer.swagger;
2 |
3 | import com.imperva.apispecparser.normalizer.NormalizedParameter;
4 | import io.swagger.models.Model;
5 | import io.swagger.models.parameters.Parameter;
6 |
7 | import java.util.HashMap;
8 | import java.util.Map;
9 |
10 | public class SwaggerNormalizedParameter implements NormalizedParameter {
11 |
12 | private final T parameter;
13 |
14 | private SwaggerDefinitions swaggerDefinitions;
15 |
16 | private int totalPropertiesCount;
17 |
18 | public SwaggerNormalizedParameter(T parameter) {
19 | this(parameter, new HashMap<>(), 0);
20 | }
21 |
22 | public SwaggerNormalizedParameter(T parameter, Map normalizedDefinitions, int totalPropertiesCount) {
23 | this.parameter = parameter;
24 | this.swaggerDefinitions = new SwaggerDefinitions(normalizedDefinitions);
25 | this.totalPropertiesCount = totalPropertiesCount;
26 | }
27 |
28 | void addDefinition(String modelName, Model model) {
29 | swaggerDefinitions.addDefinition(modelName, model);
30 | }
31 |
32 | void removeDefinition(String modelName) {
33 | swaggerDefinitions.removeDefinition(modelName);
34 | }
35 |
36 | Model getDefinition(String modelName) {
37 | return swaggerDefinitions.getDefinition(modelName);
38 | }
39 |
40 | boolean containsDefinition(String modelName) {
41 | return swaggerDefinitions.containsDefinition(modelName);
42 | }
43 |
44 | void incrementTotalPropertiesCount() {
45 | totalPropertiesCount += 1;
46 | }
47 |
48 | @Override
49 | public SwaggerDefinitions getApiDefinitions() {
50 | return swaggerDefinitions;
51 | }
52 |
53 | public int getTotalPropertiesCount() {
54 | return totalPropertiesCount;
55 | }
56 |
57 | public T getParameter() {
58 | return parameter;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/normalizer/swagger/SwaggerNormalizedPath.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.normalizer.swagger;
2 |
3 | import com.imperva.apispecparser.normalizer.NormalizedEndpoint;
4 | import com.imperva.apispecparser.normalizer.NormalizedPathImpl;
5 | import io.swagger.models.Operation;
6 | import io.swagger.models.Path;
7 |
8 | public class SwaggerNormalizedPath extends NormalizedPathImpl {
9 |
10 | private final Path path;
11 |
12 | public SwaggerNormalizedPath(Path path) {
13 | this.path = path;
14 | }
15 |
16 | public void addNormalizedEndpoint(Operation operation, SwaggerNormalizedEndpoint swaggerNormalizedEndpoint) {
17 | if (path != null && operation != null) {
18 | addNormalizedEndpoint(operation.hashCode(), swaggerNormalizedEndpoint);
19 | }
20 | }
21 |
22 | public SwaggerNormalizedEndpoint getNormalizedEndpoint(Operation operation) {
23 | if (operation == null) {
24 | return null;
25 | }
26 |
27 | NormalizedEndpoint normalizedEndpoint = super.getNormalizedEndpoint((operation.hashCode()));
28 | return normalizedEndpoint == null ? null : (SwaggerNormalizedEndpoint) normalizedEndpoint;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/parsers/ApiSpecFileLocation.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.parsers;
2 |
3 | public enum ApiSpecFileLocation {
4 | RESOURCE,
5 | EXTERNAL
6 | }
7 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/parsers/ApiSpecParser.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.parsers;
2 |
3 | import com.imperva.apispecparser.exceptions.ParseException;
4 | import com.imperva.apispecparser.model.EndpointModel;
5 |
6 | import java.util.List;
7 |
8 | public interface ApiSpecParser {
9 |
10 | List getEndpointModelList(String filePath, ApiSpecFileLocation apiSpecFileLocation) throws ParseException;
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/imperva/apispecparser/parsers/swagger/Swagger2Parser.java:
--------------------------------------------------------------------------------
1 | package com.imperva.apispecparser.parsers.swagger;
2 |
3 | import com.imperva.apiattacktool.model.tests.ParameterLocation;
4 | import com.imperva.apispecparser.exceptions.ParseException;
5 | import com.imperva.apispecparser.model.EndpointModel;
6 | import com.imperva.apispecparser.model.Property;
7 | import com.imperva.apispecparser.normalizer.swagger.SwaggerDefinitionsNormalizer;
8 | import com.imperva.apispecparser.normalizer.swagger.SwaggerNormalizedParameter;
9 | import com.imperva.apispecparser.parsers.ApiSpecFileLocation;
10 | import com.imperva.apispecparser.parsers.ApiSpecParser;
11 | import com.imperva.apispecparser.parsers.swagger.property.SimpleSwaggerPropertyFactory;
12 | import com.imperva.apispecparser.parsers.swagger.property.SwaggerAuthenticationToPropertyFactory;
13 | import com.imperva.apispecparser.parsers.swagger.propertynode.SwaggerModelToPropertyNodeFactory;
14 | import com.imperva.apispecparser.parsers.swagger.propertynode.SwaggerPropertyNodeConverter;
15 | import com.imperva.apispecparser.utils.FileUtils;
16 | import io.swagger.models.HttpMethod;
17 | import io.swagger.models.Model;
18 | import io.swagger.models.Operation;
19 | import io.swagger.models.Path;
20 | import io.swagger.models.Response;
21 | import io.swagger.models.SecurityRequirement;
22 | import io.swagger.models.Swagger;
23 | import io.swagger.models.auth.SecuritySchemeDefinition;
24 | import io.swagger.models.parameters.AbstractSerializableParameter;
25 | import io.swagger.models.parameters.BodyParameter;
26 | import io.swagger.models.parameters.Parameter;
27 | import io.swagger.parser.SwaggerParser;
28 | import org.apache.commons.lang3.StringUtils;
29 | import org.slf4j.Logger;
30 | import org.slf4j.LoggerFactory;
31 |
32 | import java.util.ArrayList;
33 | import java.util.List;
34 | import java.util.Map;
35 |
36 | public class Swagger2Parser implements ApiSpecParser {
37 |
38 | private static final Logger logger = LoggerFactory.getLogger(Swagger2Parser.class);
39 |
40 | @Override
41 | public List getEndpointModelList(String filePath, ApiSpecFileLocation apiSpecFileLocation) throws ParseException {
42 | List endpointModelList = new ArrayList<>();
43 |
44 | String fileContent = FileUtils.readFile(filePath, apiSpecFileLocation);
45 |
46 | if (fileContent == null) {
47 | return endpointModelList;
48 | }
49 |
50 | Swagger swagger = new SwaggerParser().parse(fileContent);
51 |
52 | for (Map.Entry pathEntry : swagger.getPaths().entrySet()) {
53 | for (Map.Entry httpMethodEntry : pathEntry.getValue().getOperationMap().entrySet()) {
54 |
55 | String fullPathWithParamBrackets = getNormalizedFullPath(swagger.getBasePath(), pathEntry.getKey());
56 |
57 | EndpointModel endpointModel = new EndpointModel(fullPathWithParamBrackets,
58 | com.imperva.apiattacktool.model.tests.HttpMethod.valueOf(httpMethodEntry.getKey().toString()),
59 | httpMethodEntry.getValue().getConsumes());
60 |
61 | for (Parameter parameter : httpMethodEntry.getValue().getParameters()) {
62 | Map normalizedDefinitions;
63 |
64 | if (parameter instanceof BodyParameter) {
65 | BodyParameter bodyParameter = (BodyParameter) parameter;
66 | SwaggerNormalizedParameter swaggerDefinitionNormalizerResult =
67 | SwaggerDefinitionsNormalizer.normalizeParameterDefinitions(parameter, swagger.getDefinitions());
68 | normalizedDefinitions = swaggerDefinitionNormalizerResult.getApiDefinitions().getDefinitions();
69 | SwaggerPropertyNodeConverter swaggerPropertyNodeConverter = SwaggerModelToPropertyNodeFactory.get(bodyParameter.getSchema(),
70 | bodyParameter.getRequired(), "", ParameterLocation.BODY, normalizedDefinitions);
71 |
72 | if (swaggerPropertyNodeConverter != null) {
73 | endpointModel.addNode(parameter.getName(), swaggerPropertyNodeConverter.getPropertyNode());
74 | }
75 | } else if (parameter instanceof AbstractSerializableParameter) {
76 | AbstractSerializableParameter abstractSerializableParameter = (AbstractSerializableParameter) parameter;
77 | Property property = SimpleSwaggerPropertyFactory.getPropertyFromAbstractSerializableParameter(abstractSerializableParameter,
78 | parameter.getName(), swagger.getDefinitions());
79 | endpointModel.addParameter(parameter.getName(), property);
80 | }
81 | }
82 |
83 | addResponseCodesToEndpointModel(endpointModel, httpMethodEntry.getValue().getResponses());
84 |
85 | addSecurityConfiguration(endpointModel, swagger.getSecurityDefinitions(), swagger.getSecurity(), httpMethodEntry.getValue().getSecurity());
86 |
87 | endpointModelList.add(endpointModel);
88 | }
89 | }
90 |
91 | return endpointModelList;
92 | }
93 |
94 | private static void addSecurityConfiguration(EndpointModel endpointModel, Map securityDefinitions,
95 | List apiLevelSecurity,
96 | List