# Annotated OpenAPI Security

This project aids in heightening API designers and developers awareness of the
security state of their OpenAPI Specification (OAS) APIs with respect to six of
the OWASP top 10 vulnerabilities. This will be accomplished by providing a
command line application and a library of security tooling that analyzes the OAS
document.

## Components
- `oas-cli` : The command line tool with the main class to check security validation of specifications.
- `oas-core` : The core library with features like parsing, traversing, and validating an OpenAPI Specification.
- `oas-test` : This module contains any shared testing implementations like marker interfaces for integration tests.
## Command Line Usage
The command line tool can be invoked like:

```java -jar api-security-tools.jar --file openApiSpecification.json ```

It performs:
- File validation.
- OpenApi Specification Standard validation.
- Supported security extensions validation.

If there are any errors in the usage of the extensions, then the error type and message will be shown along with the extension path.

## Building and Testing
`./gradlew build`

This will
- Compile project.
- Validate against ErrorProne and CheckStyle.
- Run both unit and integration tests.
- Generate code coverage report.

## Validator Library

The core library is responsible to traverse a YAML or JSON document and search for extensions. Every `Extension` can then be validated using custom validators.

An example is shown below.

Let's start by configuring the guice dependencies.
```
/**
 * Guice module that installs all required bindings.
 */
public class MainModule extends AbstractModule {

  @Override
  protected void configure() {
    install(new ExtendedValidatorMainModule());
    install(new BaseParserModule());
    binder().requireExplicitBindings();
  }
}
```
Create a simple validator that implements `ExtensionValidator`
```
class CustomValidator implements ExtensionValidator {

    public CustomValidator() {}

    @Override
    public ImmutableSet<ExtensionValidationMessage> validate(Extension extension) {
        // validation logic
        // extension.getExtensionPath(), extension.getExtensionContent(), extension.getExtensionName()
    }
}
```
Inject the required dependencies into your class.
```
public class ExtensionValidationExample {
    
    private BaseParser baseParser;
    private ExtendedValidator extendedValidator;
    private TraversalHelperFactory traversalHelperFactory;

    @Inject
    ExtensionValidationExample(BaseParser baseParser, 
                               ExtendedValidator extendedValidator,
                               TraversalHelperFactory traversalHelperFactory) {
        this.baseParser =baseParser;
        this.extendedValidator = extendedValidator;
        this.traversalHelperFactory = traversalHelperFactory;
    }

    void validate(File file) {
        OpenApi3 openApi = baseParser.parse(file);

        // Send traversal command for openapi object
        TraversalHelper traversalHelper = traversalHelperFactory.create(ImmutableList.of());
        traversalHelper.sendOpenApiTraversal(openApiSpec);
        ImmutableSet<Extension> extensions = traversalHelper.traverse()
        
        CustomValidator customValidator = new CustomValidator();

        // Validate an extension
        if(!extensions.isEmpty()) {
            ImmutableSet<ExtensionValidationMessage> errors = extensions.iterator().next().validate(customValidator);
            System.out.println("Found %d extension validation errors.\n\n", errors.size());
        }
    }
}

```
Run it using:

```
ExtensionValidationExample extensionValidation = Guice.createInjector(new MainModule()).getInstance(ExtensionValidationExample.class);
extensionValidation.validate(file);
```

## LICENSE

Copyright 2020 Google LLC.

Licensed under the [Apache License, Version 2.0](http://apache.org/licenses/LICENSE-2.0)
