elastic / kibana

Your window into the Elastic Stack
https://www.elastic.co/products/kibana
Other
19.62k stars 8.22k forks source link

[Security Solution] A proper location for OpenAPI specs #184859

Closed maximpn closed 4 months ago

maximpn commented 5 months ago

Epic: https://github.com/elastic/security-team/issues/9401 (internal)

Summary

While working on adding missing OpenAPI spec (OAS) for Detections API it became prominent that the current OAS placement in security_solution/common/api brings the following challenges

Currently we have io-ts schemas defined in plugins e.g. kbn-securitysolution-io-ts-list-types.

There some shared OAS schemas considered like primitives like NonEmptyString and UUID defined in Security Solution plugin. Obviously such primitives need to be reused in the other plugins.

elasticmachine commented 5 months ago

Pinging @elastic/security-solution (Team: SecuritySolution)

maximpn commented 5 months ago

One of the ideas suggested by @banderror is to use Security Solution domain packages like kbn-security-solution-detections-api and kbn-security-solution-exceptions-api. It solves the above problems in the following way

The only question is to decide where should resulting OAS bundles be placed

maximpn commented 5 months ago

Zoomed with @marshallmain and @banderror regarding this topic. Discussed possible ways to solve bad DX related to relative schema imports like ../../../../../../../lists/common/api/exceptions/exception.schema.yaml and reusing of shared primitives. Based on the discussion we worked out the following actions items

maximpn commented 5 months ago

Hi @marshallmain and @banderror,

I've investigated usage of Base URI, OAS shared schemas re-exporting and using a package for schema primitives.

TLDR: There is a no working solution out of the box. We need noticeable amount of effort to make it working.

Details

Investigate usage of Base URI

I analyzed it from two different sides OAS and JSON schema specifications and tooling (kbn-openapi-generator uses @apidevtools/swagger-parser package).

Analyzing JSON schema specification it becomes clear that references are considered as links. Links could be relative or absolute. Relative links resolved by using baseURI which is a URI the specification was retrieved from. Or baseURI can be explicitly specified via $id property. However $id property (or any alternative) isn't mentioned anywhere in OAS 3.0 specification.

I approached this part by creating a shared list schema in List plugin at x-pack/plugins/lists/common/api/values/model/list_common.schema.yaml and adding a re-export spec at x-pack/plugins/lists/common/api/export.schema.yaml looking like

openapi: 3.0.0
info:
  title: Error Schema
  version: 'not applicable'
paths: {}
components:
  x-codegen-enabled: false
  schemas:
    List:
      $ref: './values/model/list_common.schema.yaml#/components/schemas/List'

then I referenced re-exported List schema in Security Solution plugin at x-pack/plugins/security_solution/common/api/model/test_re_export.gen.ts like

openapi: 3.0.0
info:
  title: Test shared schemas re-export
  version: 'not applicable'
paths: {}
components:
  x-codegen-enabled: true
  schemas:
    TestSchema:
      type: object
      properties:
        localId:
          $ref: './primitives.schema.yaml#/components/schemas/NonEmptyString'
        listData:
          $ref: '../../../../lists/common/api/export.schema.yaml#/components/schemas/List'

The problem with that approach is that kbn-openapi-generator doesn't unfold references (a folded reference means a chain of referenced like above '../../../../lists/common/api/export.schema.yaml#/components/schemas/List' -> './values/model/list_common.schema.yaml#/components/schemas/List'). Its implementation is pretty straightforward. It simply read an OAS file and generates artefacts add imports for external references. The generated code relies on that List Zod schema exists next to export.schema.yaml in the List plugin. But it's a proxy schema we don't want to generate an artefact for.

Investigate placing OAS primitives like NonEmptyString into a package

It's not a problem to place shared schema primitives in a package. The only problem here is caused by two bullets above. Reference paths are gonna be long and looking like ../../../../../../../packages/kbn-oas-common/primitives.schema.yaml.

banderror commented 5 months ago

@maximpn Thank you for doing this research and describing the results. My suggestion is:

maximpn commented 4 months ago

Based on the research we decided to proceed with packages for OpenAPI specs as describe in the previous comment https://github.com/elastic/kibana/issues/184859#issuecomment-2160485108.

Actual code change will be addressed as a part of separate tickets