Enforce content type on barbican REST API¶
Include the URL of your launchpad blueprint:
https://blueprints.launchpad.net/barbican/+spec/barbican-enforce-content-type
Before barbican moved from falcon to pecan, content types were coerced to application/json. This meant that a user could use a tool such as curl, omit the content type, and the call would succeed. After moving to pecan, the default content-type changed to application/x-www-form-urlencoded. This meant that a curl request without a content type specified would end up coming into barbican as a urlencoded string and would fail during JSONifying.
Problem Description¶
As a result of the move from falcon to pecan, the default content type for requests has changed from application/json to application/xxx-www-form-urlencoded. That means that calls without a content-type which used to work with the falcon implementation will now fail with the pecan implementation.
If a caller sets their content-type header to application/json then everything works as expected.
However, if a caller omits the content-type header then it now defaults to application/xxx-www-form-urlencoded. This means that pecan will URLencode the request body, and that causes barbican to fail when it tries to JSONify it.
Proposed Change¶
The proposed change is to check the content-type header on the following types of Barbican requests, and reject any request (via pecan abort with HTTP 415) that does not specify the correct value:
Resource |
HTTP Verb |
Enforced Content Types |
---|---|---|
Secret |
PUT |
application/octet-stream text/plain |
Secrets |
POST |
application/json |
Orders |
POST |
application/json |
Containers |
POST |
application/json |
TransportKeys |
POST |
application/json |
Alternatives¶
There are alternatives to the proposed change:
Change the content-type header to the correct value. This would resolve the problem described above, but could have unintended consequences as the user’s input data would be changed from what they provided/expected.
Detect the situation where the default was taken for content-type and compensate by:
URL-decoding the string
cleanup any padding characters that may have been added
Data model impact¶
None.
REST API impact¶
Users of the following resources will have to provide a valid value in their content-type header on REST API calls as indicated below:
Resource |
HTTP Verb |
Required Content Types |
---|---|---|
Secret |
PUT |
application/octet-stream or text/plain |
Secrets |
POST |
application/json |
Orders |
POST |
application/json |
Containers |
POST |
application/json |
TransportKeys |
POST |
application/json |
Security impact¶
None.
Notifications & Audit Impact¶
None.
Other end user impact¶
None.
Performance Impact¶
Each REST call will now incur a check of the content-type. Calls without the correct content-type will fail with pecan.abort and HTTP 415.
Other deployer impact¶
None.
Developer impact¶
Developers who use a tool such as curl will need to ensure that they pass content-type:application/json in their HTTP headers, otherwise they will fail with HTTP 415.
Implementation¶
Assignee(s)¶
- Primary assignee:
sheyman
- Other contributors:
john-wood-w arunkant-uws
Work Items¶
There are 3 work items required for this change:
updating the barbican code to detect incorrect content types and pecan abort with HTTP 415
updating the barbican documentation to describe this change and provide recovery action
updating the barbican tests to validate the behavior of the new code. This includes unit and functional tests.
Dependencies¶
None.
Testing¶
The following positive test scenarios will be needed for this proposed change:
Resource |
Verb |
Content-Type |
Expected Result |
---|---|---|---|
Secret |
PUT |
application/octet-stream |
success |
Secret |
PUT |
text/plain |
success |
Secrets |
POST |
application/json |
success |
Orders |
POST |
application/json |
success |
Containers |
POST |
application/json |
success |
Transport Keys |
POST |
application/json |
success |
In addition, the following negative tests will be used to verify behavior:
Resource |
Verb |
Content-Type |
Expected Result |
---|---|---|---|
Secret |
PUT |
none (omitted) |
HTTP 415 |
Secret |
PUT |
application/octet-streamx |
HTTP 415 |
Secret |
PUT |
text/plainx |
HTTP 415 |
Secret |
PUT |
applicationx/octet-stream |
HTTP 415 |
Secret |
PUT |
textx/plain |
HTTP 415 |
Secret |
PUT |
application/json |
HTTP 415 |
Resource |
Verb |
Content-Type |
Expected Result |
---|---|---|---|
Secrets |
POST |
none (omitted) |
HTTP 415 |
Secrets |
POST |
text/plain |
HTTP 415 |
Secrets |
POST |
application/octet-stream |
HTTP 415 |
Secrets |
POST |
application/jsonx |
HTTP 415 |
Secrets |
POST |
applicationx/json |
HTTP 415 |
Secrets |
POST |
application/jsonx |
HTTP 415 |
Resource |
Verb |
Content-Type |
Expected Result |
---|---|---|---|
Orders |
POST |
none (omitted) |
HTTP 415 |
Orders |
POST |
text/plain |
HTTP 415 |
Orders |
POST |
application/octet-stream |
HTTP 415 |
Orders |
POST |
application/jsonx |
HTTP 415 |
Orders |
POST |
applicationx/json |
HTTP 415 |
Orders |
POST |
application/jsonx |
HTTP 415 |
Resource |
Verb |
Content-Type |
Expected Result |
---|---|---|---|
Containers |
POST |
none (omitted) |
HTTP 415 |
Containers |
POST |
text/plain |
HTTP 415 |
Containers |
POST |
application/octet-stream |
HTTP 415 |
Containers |
POST |
application/jsonx |
HTTP 415 |
Containers |
POST |
applicationx/json |
HTTP 415 |
Containers |
POST |
application/jsonx |
HTTP 415 |
Resource |
Verb |
Content-Type |
Expected Result |
---|---|---|---|
Transport Keys |
POST |
none (omitted) |
HTTP 415 |
Transport Keys |
POST |
text/plain |
HTTP 415 |
Transport Keys |
POST |
application/octet-stream |
HTTP 415 |
Transport Keys |
POST |
application/jsonx |
HTTP 415 |
Transport Keys |
POST |
applicationx/json |
HTTP 415 |
Transport Keys |
POST |
application/jsonx |
HTTP 415 |
Documentation Impact¶
Documentation will need to specify that the content-type header is now required for the API/verbs shown above under “Proposed Change”. Omitted content-type, or content-type other than the allowed values will result in an HTTP 415.
NOTE: current documentation says that a secret PUT “should” include the appropriate content-type. That will have to be updated to “must”. See https://github.com/cloudkeep/barbican/wiki/Application-Programming-Interface#put
References¶
The following bugs and proposed fixes led to the creation of this blueprint: