StackHawk Documentation StackHawk Logo HawkDocs

No results found

Try different keywords or check your spelling

Search documentation

Find guides, API references, and more

esc

OpenAPI Configuration

The OpenAPI Specification (AKA Swagger) is an industry-adopted standard for describing RESTful interfaces, which HawkScan can use to deliver a faster, more thorough scan.

HawkScan uses your OpenAPI spec to improve scan quality by:

  • Pre-seeding the sitemap with routes from your spec—complementing or replacing app spidering
  • Using defined inputs to better understand how to communicate with and test endpoints

HawkScan supports both OpenAPI v2 and v3, as separate files or inline in your stackhawk.yml. Note: inline specs cannot exceed 4MB.

Creating an OpenAPI Spec

If your project doesn’t have an OpenAPI spec, there are multiple ways to get started. Even for internal APIs, an OpenAPI spec is useful for integration with HawkScan and many other tools.

Example OpenAPI Spec File

A typical OpenAPI spec can be defined in either YAML or JSON format (e.g. openapi.yml). A YAML version might look like the following:

swagger: "2.0"
info:
  title: Sample Example Web API
  description: Web API description in _markdown_.
  version: 1.0.0
host: api.example.com
basePath: /v1
schemes:
  - https
paths:
  /users:
    get:
      summary: Returns a list of users.
      description: extended description in Markdown.
      produces:
        - application/json
      responses:
        200:
          description: OK

Using an OpenAPI Spec File in HawkScan

If your project already uses an existing v3 OpenAPI specification, you can integrate it with HawkScan with the app.openApiConf parameter.

For example, if your app serves the OpenAPI spec on the URL path /openapi.yaml, include the following in your stackhawk.yml configuration.

app:
  openApiConf:
    # Specify the URL path relative to the host
    path: "/openapi.yaml"

Or if you have the spec defined in a local file, openapi.json, provide the relative path to that file with the following config.

app:
  openApiConf:
    # Specify the relative path to the file
    filePath: "openapi.json"

Or if the running application serves API defined over many specification files, you can list them all together.

app:
  openApiConf:
    # Specify the relative paths to many files
    filePaths:
      - "frontend/openapi-app.json"
      - "backend/openapi-auth.json"
      - "admin/openapi-admin.json"

Using an OpenAPI Spec File from OpenAPI Spec Gen

StackHawk Applications mapped to code repositories with enabled API Discovery can additionally utilize OpenAPI Specification Generation to scan a running web application with the OpenAPI Specification generated for those repositories and the API sources within them.

app:
  openApiConf:
    filePaths:
      - hawk://41ed1b96-406e-45d3-989c-c743c24a4798
      - hawk://9742f249-21a6-41f5-ab15-aa56d61c5861

Additionally checking the box next to a StackHawk generated specification will include it as part of running HawkScan with the simple usePlatform: true configuration. Platform hosted specifications will be downloaded and used to drive HawkScan when configured this way.

app:
  openApiConf:
    usePlatform: true

This configuration requires the scanned application to have at least one StackHawk-generated and included OpenAPI specification from the platform.

Using an Inline OpenAPI Spec in HawkScan

You can define portions of your web app structure within the app.openApiConf.inline configuration of your stackhawk.yml in the OpenAPI format:

# in the "app" config...
app:
  # instead of a string path to a file, provide the openapi spec inline as a multi-line string with the yaml | pipe syntax
  openApiConf:
    inline: |
      basePath: /v1           
      schemes:                
      - https                 
      paths:                  
        /users:               
          get:                
            summary: Returns a list of users.
            description: extended description in Markdown.
            produces:         
              - application/json
            responses:        
              200:            
                description: OK

This can be useful for segmenting scan results to portions of your web application. It can also start as the foundation of more thorough API documentation to start your own openapi.yaml specification file.

Reminder that your inline spec cannot exceed 4MB!

Using Custom Variable Injection

By default, DELETE methods will not use the custom values provided in the stackhawk.yml file to protect data from being deleted by the scanner. If you want to include custom variables in ALL methods, you can set the app.openApiConf.includeAllMethods parameter to true. If you would rather specify exactly which methods to use custom variables with, you may set them with the app.openApiConf.includedMethods list. This list will be ignored if the includeAllMethods parameter is set to true.

The following is an example configuration using custom values:

# in the "app" config...
app:
  openApiConf:
    filePath: "/openapi.yaml"
    # Whether or not to use custom variables for all HTTP methods. Defaults to false and does not use custom variables for DELETE requests. 
    includeAllMethods: false
    # The methods to include in custom variable injection. If `includeAllMethods` is set to true, this list is ignored. Otherwise, only the methods provided will use custom variables.
    includedMethods:
      - POST
      - PUT
    # List of custom variables and a list of possible values to use for each of them.  
    customVariables:
      - field: user_id
        values:
          - 1
          - 2
          - 3
      - field: asset_id
        values:
          - 4
          - 5
          - 6
      - field: asset_title
        values:
          - "testAssetTitle1"
          - "testAssetTitle2"
      - field: username
        values:
          - "testAccountUsername"

To achieve greater control over OpenAPI custom variables, you have the option to include a path regex and a list of request methods. These additional filters help in injecting custom variable values more selectively. When a path regex and/or a list of request methods are specified, only requests that match that specific information will utilize the provided list of values for variable injection. This allows you to assign different sets of values for the same schema parameter name. For instance, if you have two separate endpoints that both use the {userId} parameter, you can use the path regex to assign distinct lists of potential values for each endpoint. Here’s an example of how to configure paths and methods:

# in the "app" config...
app:
  openApiConf:
    filePath: "/openapi.yaml"
    # Whether or not to use custom variables for all HTTP methods. Defaults to false and does not use custom variables for DELETE requests. 
    includeAllMethods: true
    # List of custom variables and a list of possible values to use for each of them.  
    customVariables:
      - field: searchText
        values:
          - "customSearchText1"
          - "customSearchText2"
          - "customSearchText3"
        path: "/api/v1/jwt/items/search"
        requestMethods:
          - GET
          - POST
      - field: searchText
        values:
          - "customSearchText4"
          - "customSearchText5"
          - "customSearchText6"
        path: "/api/v2/jwt/items/search"
        requestMethods:
          - GET
          - POST      

In the example above, when substituting the searchText parameter for v1 endpoints, it will utilize the custom values 1, 2, and 3. However, for v2 endpoints, the injection will instead use custom values 4, 5, and 6. Additionally, when considering the requestMethods, the injection of values will only occur if the request is either a GET or a POST.

Generating Smart Values for Parameters

In the various schema sections that exist within your definition, if a format field exists with a known type, a random value will be generated in the specified format. For example:

paths:
  /search:
    get:
      parameters:
        - in: query
          name: user_email
          type: string
          format: email
      responses:
        200:
          description: OK

When a value for the parameter user_email is generated by HawkScan and an explicit custom value is not provided, then a random, valid email address will be generated for each path the parameter appears in. Another way to leverage this functionality, if you don’t have access to or don’t want to change the OpenAPI definition, is to inject a format similar to a custom variable, described in the section above. To configure a custom variable, supply the faker prefix along with the desired format to generate a corresponding value. For example, to generate a phone number for a parameter called customer_phone_number and an email for customer_email use the following configuration:

  openApiConf:
    filePath: "/myopenapi.yaml"
    fakerEnabled: true #default false
    customVariables:
      - field: customer_email
        values:
          - "$faker:email"
      - field: customer_phone_number
        values:
          - "$faker:phone"
          - "123456767"

Faker values can be used together with custom variables. In the example above, customer_phone_number is given 2 potential values, a static value, and a faker format. One of the 2 will be chosen randomly when a value is generated, and if the faker value is chosen, then a properly formatted random value will be generated.

Along with generating values for these formats, the minimum and maximum constraints will also be respected, if provided, for all numbers/integers in the OpenAPI definition.

Tips for Creating a New OpenAPI Spec for HawkScan

Because OpenAPI is widely adopted, there are a lot of available tools to help a project get started: https://openapi.tools/

SmartBear has free online editor that can be used immediately to start building a OpenAPI file that will work with HawkScan: https://swagger.io/tools/swagger-editor/

For new projects, the industry recommended approach is to create an OpenAPI spec file and employ OpenAPI code-generators to stub out the endpoints for the desired server frameworks. For existing projects, there are various ways to get an OpenAPI specification defined.

Framework specific help:

Amazon API Gateway

Amazon’s API Gateway allows you to export a REST API as an OpenAPI spec.

You can export an OpenAPI v2 .json file with the AWS CLI using a command like:

aws apigateway get-export \
  --parameters extensions='apigateway' \
  --rest-api-id <restapi_id> \
  --stage-name <stage_name> \
  --export-type swagger openapi.json

Note: You can get the restapi_id and stage_name using these commands.

aws apigateway get-rest-apis
aws apigateway get-stages --rest-api-id=<restapi_id>

Now add that new openapi.json file to the stackhawk.yml.

app:
  openApiConf:
    filePath: "openapi.json"

ASP.NET

The Swashbuckle package will expose an OpenAPI spec for the app via a URL.

Install the package:

Install-Package Swashbuckle

Enable Swashbuckle in something like Program.cs

httpConfiguration
  .EnableSwagger(c => c.SingleApiVersion("v1", "A title for your API"))
  .EnableSwaggerUi();

Then download the spec to a file from the URL: <your-root-url>/swagger/docs/v1

Add that new file to the stackhawk.yml

app:
  openApiConf:
    filePath: "myproj.json"

Note: The above steps are for if your app is hosted in IIS. If it’s not, please look at the the Swashbuckle docs for similar install instructions.

Django

Django projects can use the Django REST swagger Python package to generate an OpenAPI v2 spec file with their code.

Run pip install django-rest-swagger and add the following to your Django settings:

INSTALLED_APPS = [
  ...
  'rest_framework_swagger',
  ...
]

Express

There isn’t a way to automatically find and define routes for OpenAPI, but a good way to start is to output all the app’s routes and then use something like swagger-jsdoc to document them.

Find all your routes with some code like this:

var route, routes = [];

app._router.stack.forEach(function(middleware){
  if(middleware.route){ // routes registered directly on the app
    routes.push(middleware.route);
  } else if(middleware.name === 'router'){ // router middleware
    middleware.handle.stack.forEach(function(handler){
      route = handler.route;
      route && routes.push(route);
    });
  }
});

routes.forEach(function(temp){
  var methods = "";
  for(var method in temp.methods){
    methods += method + ", ";
  }
  console.log(temp.path + ": " + methods);
});

Set up swagger-jsdoc and then document each route: https://github.com/Surnet/swagger-jsdoc/#getting-started

/**
 * @swagger
 *
 * /login:
 *   post:
 *     description: Login to the application
 *     produces:
 *       - application/json
 *     parameters:
 *       - name: username
 *         description: Username to use for login.
 *         in: formData
 *         required: true
 *         type: string
 *       - name: password
 *         description: User's password.
 *         in: formData
 *         required: true
 *         type: string
 *     responses:
 *       200:
 *         description: login
 */
app.post('/login', (req, res) => {
  // Your implementation comes here ...
});

PHP

Laravel and other PHP frameworks can utilize zircote/swagger-php to generate OpenAPI spec files by using code annotations. For OpenAPI v2 spec generation you can explicitly require version 2._ with composer require zircote/swagger-php:2._. The SWAGGER_VERSION=2.0 environment variable will need to be set in your .env file or defined with export SWAGGER_VERSION=2.0

Add phpdoc annotations to your code to assist with OpenAPI spec generation. When you build your site a swagger.json file will be written out to the local working directory.

/**
 * @OA\Info(title="My First API", version="0.1")
 */

/**
 * @OA\Get(
 *     path="/api/resource.json",
 *     @OA\Response(response="200", description="An example resource")
 * )
 */

/** Generate documentation with your php site */
<?php
require("vendor/autoload.php");
$openapi = \OpenApi\scan('/path/to/project');
header('Content-Type: application/x-yaml');
echo $openapi->toYaml();

Postman Collection

When an application lacks an OpenAPI specification but has a Postman Collection available, that collection can be exported as json and then converted into an OpenAPI spec file using various tools, such as postman-to-openapi (local option; requires node.js)

Rails

There isn’t a way to automatically find and define routes for OpenAPI, but a good way to start is to output all the app’s routes and then use something like swagger-docs to document them.

List out the app’s routes with rails routes

Set up swagger-docs and document each route: https://github.com/richhollis/swagger-docs

swagger_controller :users, "User Management"

swagger_api :index do
  param :query, :page, :integer, :optional, "Page number"
  response :unauthorized
  response :not_acceptable
  response :requested_range_not_satisfiable
end

Spring/Springboot

SpringDoc is a java library that helps to generate OpenAPI v3 spec files from configuration, class structure and annotated controllers in projects using spring boot. It exposes the generated OpenAPI file from a configured rest endpoint.

Add the SpringDoc-OpenAPI dependency to your maven build pom file:

<dependency>
  <groupId>org.springdoc</groupId>
  <artifactId>springdoc-openapi-ui</artifactId>
  <version>1.6.9</version>
</dependency>

Or add the dependency to your Gradle build file:

implementation("org.springdoc:springdoc-openapi-ui")

Also add any additional springdoc modules pertinent to your project. Springdoc also defines extensive spring configuration properties for smarter openapi file generation and spec customization.

Springdoc provides additional controller and method annotations such as @Operation @Parameter @Tag that work with typical spring boot @RequestMapping and @RestController annotations:

// example spring controllers annotated with springdoc

@RestController
@RequestMapping("/api/pets")
@Tag(name = "Pet", description = "Everything about your Pets")
public class PetController {

  @Operation(summary = "Find a pet by Status", description = "Longer description...")
  @RequestMapping(value = "/findByStatus", method = RequestMethod.GET, params = {"status"})
  public Pet findPetsByStatus(
    @Parameter(description = "the status of the pet")
    @RequestParam("status", defaultValue="ok") String status
  ) {
    // ...
  }

  @Operation(summary = "Updates a pet in the store", description = "Longer description...")
  @RequestMapping(value = "/{petId}", method = RequestMethod.POST)
  public ResponseEntity<String> updatePet(
    @Parameter(description = "ID of pet that needs to be updated")
    @PathVariable("petId") String petId
  ) {
    // ...
  }
}

The spec can then be downloaded to a local file by reaching the configured endpoint.

curl localhost:8080/v3/api-docs > openapi.json

With the openapi.json spec downloaded and available, the stackhawk.yml can be updated:

app:
  openApiConf:
    filePath: "openapi.json"

This guide previously recommended a different library called SpringFox for generating a v2 OpenAPI spec. If needed, you can follow the SpringFox migration guide to replace the deprecated implementation.

Validating An OpenAPI Specification

Once an OpenAPI spec has been generated using one of the methods described above, it can be validated using the official Swagger editor:

  1. paste in the contents of the spec file — this page will dynamically generate and resolve errors as the specification is edited on the page
  2. apply edits as necessary
  3. supply the updated spec to the scanner via the app.openApiConf configuration
  4. scan the application
    1. if further issues or errors are encountered, contact StackHawk Support for assistance

Your privacy settings

We use first and third party cookies to ensure that we give you the best experience on our website and in our products.