406 response from NetHSM, Docker image nitrokey/nethsm:testing and nethsm-api.yaml

Hi,

I have been using the nitrokey/nethsm:testing docker image for testing my API client library in Go.

Today I regenerated REST code using OpenAPI Generator and the https://nethsmdemo.nitrokey.com/api_docs/nethsm-api.yaml OpenAPI specification and noticed that the nethsm-api.yaml file has probably changed a bit so that, for instance, this call:

/keys/{KeyID}/csr.pem:
    post:
      responses:
        "200":
          description: Successful generation of certificate signing request.
          content:
            application/x-pem-file:
              schema:
                $ref: "#/components/schemas/PemCSR"
        "400":
          description: Bad request (specified properties are invalid).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Authentication required but none provided.
        "403":
          description: Access denied.
        "404":
          description: Key for KeyID not found in namespace.
        "406":
          description: Content type in Accept header not supported.
        "412":
          description: Precondition failed (NetHSM was not *Operational*).

now results in a client that will accept application/x-pem-file AND application/json where before it would only accept application/x-pem-file.

So when I run my tests against the Docker test container the response I get is a 406 Content type in Accept header not supported. Which suggests to me that the Docker image (or the HSM software) and the API definition are not entirely in sync.

I’m not quite sure how to address this. For now I think I’ll keep the generated code made from what I assume is an older version of the OpenAPI spec.

I think it could be helpful if different versions of the OpenAPI spec were published under a filename that has the version of the OpenAPI in it so it is possible to use a specific version when generating code.

Is it possible to make the HSM software be somewhat more tolerant of Accept headers?

It looks like this is related to this commit:

This adds a specification for error responses that are of type application/json to a bunch of API calls. Some of these (like /keys/{KeyID}/csr.pem) used to returned something other that application/json before, so when the server seens an accept header from the client that includes application/json it returns 406 Content type in Accept header not supported even though the OpenAPI spec says it does.

When code generators generate clients from the OpenAPI spec they will add all of the response types that are listed in the spec to the Accept header. Which any older versions of the software will not accept.

The easiest way to make sure that other clients don’t trip up here would probably be to publish multiple versions of the spec so that an OpenAPI spec that works with older versions of the server are easy to find for developers.

The solution I will be experimenting with in my Go library is to just add a mechanism that rewrites the headers in the http.Client and removes the application/json Accept headers for the affected calls. This isn’t an optimal solution, but it should work.

(I would recommend having semantic versioning of the OpenAPI spec, and having tests that ensure changes within the same major version doesn’t break compatibility :slightly_smiling_face: )

I managed to create a workaround in the GitHub - borud/nethsm: NetHSM Client library Go library. I just omit the Accept header in the HTTP request and that seems to work fine. It probably isn’t ideal, but it appears to work.