diff --git a/pom.xml b/pom.xml index 687ae59..938e097 100644 --- a/pom.xml +++ b/pom.xml @@ -181,6 +181,16 @@ com.webfuzzing.commons.report + + auth.yaml + + generate + + + ${basedir}/src/main/resources/wfc/schemas/auth.yaml + com.webfuzzing.commons.auth + + diff --git a/release_notes.md b/release_notes.md index c220ee0..0aa8b7b 100644 --- a/release_notes.md +++ b/release_notes.md @@ -1,3 +1,6 @@ +# 0.0.2 +Support for auth + # 0.0.1 First draft version \ No newline at end of file diff --git a/src/main/resources/wfc/schemas/auth.yaml b/src/main/resources/wfc/schemas/auth.yaml index cac6867..9b0de6c 100644 --- a/src/main/resources/wfc/schemas/auth.yaml +++ b/src/main/resources/wfc/schemas/auth.yaml @@ -11,12 +11,12 @@ properties: description: "List of authentication information for different users." type: array items: - $ref: "#/$def/AuthenticationInfo" + $ref: "#/$defs/AuthenticationInfo" authTemplate: description: "Optional authentication information template. This is used to avoid duplication in the auth list. \ Entries defined in the template will be applied to all elements in the auth list that do not specify them." allOf: - - $ref: "#/$def/AuthenticationInfo" + - $ref: "#/$defs/AuthenticationInfo" - type: object configs: description: "Optional map of configuration parameters, in the form key:value strings. \ @@ -26,9 +26,140 @@ properties: additionalProperties: type: string required: ["auth"] -$def: +$defs: +# TODO unfortunately, tools like jsonschema2pojo-maven-plugin have major limitations when dealing with enums. +# This is not created as a top-level class + HttpVerb: + type: string + enum: + - POST + - GET + - PATCH + - DELETE + - PUT + Header: + description: "HTTP header information" + type: object + properties: + name: + description: "The header name, e.g., 'Authorization'." + type: string + value: + description: "The value of the header" + type: string + required: ["name","value"] AuthenticationInfo: type: object - - - + properties: + name: + description: "The name given to this authentication info. \ + This works as a unique id for this authentication configuration." + type: string + requireMockHandling: + description: "Specify that the authentication for this user requires setting up mock responses from an external service. \ + This will be done as part of the fuzzing, although only possible for white-box testing. \ + One consequence here is that, even if we provide correct auth info as input, then a request might still \ + fail due to unauthorized access if the fuzzing process does not properly set up these mocked responses in the API itself." + type: boolean + fixedHeaders: + description: "The headers needed for authentication. \ + This is used to represent cases in which auth info is static/fixed, e.g., \ + when passing an id or username/password through a HTTP header (and not \ + using for example a dynamically generated token from a login endpoint first)." + type: array + items: + $ref: "#/$defs/Header" + loginEndpointAuth: + $ref: "#/$defs/LoginEndpoint" + required: ["name"] + ### + LoginEndpoint: + description: "Used to represent the case in which a login endpoint is used to obtain the authentication credentials. \ + These can be cookies, or a token extracted from the login endpoint's response. \ + This token can then be added to an HTTP header in the following requests." + type: object + properties: + endpoint: + description: "The endpoint path (eg '/login') where to execute the login. \ + It assumes it is on same server of API.\ + If not, rather use 'externalEndpointURL'." + type: string + externalEndpointURL: + description: "If the login endpoint is on a different server, here can rather specify the full URL for it." + type: string + payloadRaw: + description: "The raw payload to send, as a string." + type: string + payloadUserPwd: + $ref: "#/$defs/PayloadUsernamePassword" + headers: + description: "HTTP headers needed when calling the login endpoint. \ + Username/password could be passed by headers instead of by the body payload." + type: array + items: + $ref: "#/$defs/Header" + verb: +# description: "The verb used to connect to the login endpoint. \ +# Most of the time, this will be a 'POST'." +# type: string +# enum: +# - POST +# - GET +# - PATCH +# - DELETE +# - PUT + $ref: "#/$defs/HttpVerb" + ## FIXME: unfortunately, plugin is not able to handle this... need new schema version with $ref not replacing everything +# description: "The verb used to connect to the login endpoint. \ +# Most of the time, this will be a 'POST'." +# allOf: +# - $ref: "#/$defs/HttpVerb" +# - type: string + contentType: + description: "Specify the format in which the payload is sent to the login endpoint. \ + A common example is 'application/json'." + type: string + token: + $ref: "#/$defs/TokenHandling" + expectCookies: + description: "Specify if we are expecting to get cookies from the login endpoint. \ + If so, a fuzzer can use those as auth info in following requests, instead of trying to extract \ + an auth token from the response payload." + type: boolean + required: ["verb"] + ### + TokenHandling: + description: "Specify how to extract token from response, and how to use it for auth in following requests. \ + Not needed if rather expect to get back a cookie." + type: object + properties: + extractFromField: + description: "How to extract the token from a JSON response, as such JSON could have few fields, possibly nested. \ + It is expressed as a JSON Pointer (RFC 6901)." + type: string + httpHeaderName: + description: "When sending a token in an HTTP header, specify to which header to add it (e.g., 'Authorization')." + type: string + headerPrefix: + description: " When sending out the obtained token in an HTTP header, specify if there should be any \ + prefix (e.g., 'Bearer ' or 'JWT '). If needed, make sure it has trailing space(s)." + type: string + ### + PayloadUsernamePassword: + description: "Payload with username and password information. \ + It will be automatically formatted in a proper payload based on content type." + type: object + properties: + username: + description: "The id of the user." + type: string + password: + description: "The password of the user, in plain-text. This must NOT be hashed." + type: string + usernameField: + description: "The name of the field in the body payload containing the username." + type: string + passwordField: + description: "The name of the field in the body payload containing the password" + type: string + required: ["username","usernameField","password","passwordField"] \ No newline at end of file diff --git a/src/main/resources/wfc/schemas/report.yaml b/src/main/resources/wfc/schemas/report.yaml index 4fe2b91..750c62c 100644 --- a/src/main/resources/wfc/schemas/report.yaml +++ b/src/main/resources/wfc/schemas/report.yaml @@ -19,18 +19,18 @@ properties: format: date-time description: "The timestamp of when this report file was created." faults: - $ref: "#/$def/Faults" + $ref: "#/$defs/Faults" #### Unfortunately, there is no support for oneOf in jsonschema2pojo # problem_details: # type: object # oneOf: -# - $ref: "#/$def/RESTReport" +# - $ref: "#/$defs/RESTReport" # # TODO GraphQL, RPC and Web problem_details: type: object properties: rest: - $ref: "#/$def/RESTReport" + $ref: "#/$defs/RESTReport" # TODO GraphQL, RPC and Web # expressing that only 1 should be present is possible, but super-verbose and convoluted total_tests: @@ -40,24 +40,24 @@ properties: test_file_paths: type: array items: - $ref: "#/$def/TestFilePath" + $ref: "#/$defs/TestFilePath" uniqueItems: true description: "The list of relative paths (compared to this document) of all the generated test suite files." test_cases: description: "Information on each generated test case." type: array items: - $ref: "#/$def/TestCase" + $ref: "#/$defs/TestCase" #OPTIONAL extra: description: "Extra, optional coverage information, collected by different tools." type: array items: - $ref: "#/$def/Coverage" + $ref: "#/$defs/Coverage" required: ["schema_version","tool_name","tool_version","creation_time","faults","problem_details","total_tests","test_file_paths","test_cases"] -$def: +$defs: OperationId: description: "A unique identifier for an operation. For example, in REST, it would be a HTTP endpoint, including verb, e.g., 'GET:/users/{id}'." @@ -85,15 +85,15 @@ $def: type: object properties: endpoint_id: - $ref: "#/$def/OperationId" + $ref: "#/$defs/OperationId" test_case_id: - $ref: "#/$def/TestCaseId" + $ref: "#/$defs/TestCaseId" http_status: description: "As in a test case the same endpoint could be called more than once, here we report all of the obtained HTTP status codes" type: array items: - $ref: "#/$def/HttpStatus" + $ref: "#/$defs/HttpStatus" minItems: 1 uniqueItems: true required: ["endpoint_id","test_case_id","http_status"] @@ -107,13 +107,13 @@ $def: type: object properties: operation_id: - $ref: "#/$def/OperationId" + $ref: "#/$defs/OperationId" test_case_id: - $ref: "#/$def/TestCaseId" + $ref: "#/$defs/TestCaseId" fault_categories: type: array items: - $ref: "#/$def/FaultCategoryId" + $ref: "#/$defs/FaultCategoryId" minItems: 1 uniqueItems: true required: ["endpoint_id","test_case_id","fault_categories"] @@ -130,22 +130,22 @@ $def: description: "Unique ids of all the endpoints in the tested API." type: array items: - $ref: "#/$def/OperationId" + $ref: "#/$defs/OperationId" uniqueItems: true covered_http_status: description: "List of which HTTP status codes were covered, based on endpoints." type: array items: - $ref: "#/$def/CoveredEndpoint" + $ref: "#/$defs/CoveredEndpoint" required: ["total_http_calls","endpoint_ids","covered_http_status"] TestCase: type: object properties: id: - $ref: "#/$def/TestCaseId" + $ref: "#/$defs/TestCaseId" file_path: - $ref: "#/$def/TestFilePath" + $ref: "#/$defs/TestFilePath" name: description: "The name of the test case, as it appears in the generated test file." type: string @@ -171,7 +171,7 @@ $def: description: "Information on all the identified potential faults." type: array items: - $ref: "#/$def/FoundFault" + $ref: "#/$defs/FoundFault" required: ["total_number","found_faults"] Coverage: @@ -183,7 +183,7 @@ $def: criteria: type: array items: - $ref: "#/$def/CoverageCriterion" + $ref: "#/$defs/CoverageCriterion" required: ["tool_name","criteria"] CoverageCriterion: diff --git a/web-report/src/types/GeneratedTypes.tsx b/web-report/src/types/GeneratedTypes.tsx index d236ef9..c82155c 100644 --- a/web-report/src/types/GeneratedTypes.tsx +++ b/web-report/src/types/GeneratedTypes.tsx @@ -5,6 +5,20 @@ * and run json-schema-to-typescript to regenerate this file. */ +/** + * A unique identifier for an operation. For example, in REST, it would be a HTTP endpoint, including verb, e.g., 'GET:/users/{id}'. + */ +export type OperationId = string; +/** + * A unique identifier for a test case. It could include its name and file location. + */ +export type TestCaseId = string; +export type HttpStatus = number; +/** + * A relative path used to unique locate a test suite file. + */ +export type TestFilePath = string; + /** * Schema Definition for Web Fuzzing Commons Reports */ @@ -37,7 +51,7 @@ export interface WebFuzzingCommonsReport { /** * The list of relative paths (compared to this document) of all the generated test suite files. */ - test_file_paths: string[]; + test_file_paths: TestFilePath[]; /** * Information on each generated test case. */ @@ -63,14 +77,8 @@ export interface Faults { * Data-structure to represent found faults, based on operations (e.g., HTTP endpoints in REST, and methods in GraphQL and RPC) and which tests find faults in them. */ export interface FoundFault { - /** - * A unique identifier for an operation. For example, in REST, it would be a HTTP endpoint, including verb, e.g., 'GET:/users/{id}'. - */ - operation_id?: string; - /** - * A unique identifier for a test case. It could include its name and file location. - */ - test_case_id: string; + operation_id?: OperationId; + test_case_id: TestCaseId; /** * @minItems 1 */ @@ -99,7 +107,7 @@ export interface RESTReport { /** * Unique ids of all the endpoints in the tested API. */ - endpoint_ids: string[]; + endpoint_ids: OperationId[]; /** * List of which HTTP status codes were covered, based on endpoints. */ @@ -110,31 +118,19 @@ export interface RESTReport { * Data-structure to represent which HTTP status code where covered on an endpoint by any of the generated tests. */ export interface CoveredEndpoint { - /** - * A unique identifier for an operation. For example, in REST, it would be a HTTP endpoint, including verb, e.g., 'GET:/users/{id}'. - */ - endpoint_id: string; - /** - * A unique identifier for a test case. It could include its name and file location. - */ - test_case_id: string; + endpoint_id: OperationId; + test_case_id: TestCaseId; /** * As in a test case the same endpoint could be called more than once, here we report all of the obtained HTTP status codes * * @minItems 1 */ - http_status: [number, ...number[]]; + http_status: [HttpStatus, ...HttpStatus[]]; [k: string]: unknown; } export interface TestCase { - /** - * A unique identifier for a test case. It could include its name and file location. - */ - id?: string; - /** - * A relative path used to unique locate a test suite file. - */ - file_path?: string; + id?: TestCaseId; + file_path?: TestFilePath; /** * The name of the test case, as it appears in the generated test file. */