formpost middleware change

Registered by Venkat Sundaram on 2013-05-31

The existing swift middleware has a formPOST filter that translates a browser form post into a regular Swift object PUT. The signature algorithm used is fixed to HMAC-SHA1 (RFC 2104). In other words, the formPOST filter can handle only HMAC-SHA1 signed URLs. This is limiting if the client wants to use a different signature alogrithm. Also, should swift decide to support multiple algorithms, the formPOST filter code has to change. This calls for a signature algorithm agnostic way to validate the signature

Further, validating the signature in the middleware itself requires storing the user specified secretKey with each Swift account. As the strength of the key depends on what the customer chooses, this increases the chances of compromising the secretKey. Its desirable to de-couple security from storage and delegate validation to keystone, which offers a reliable algorithm using accessKey/secretKey pair. This also provides flexibility in supporting more signature algorithms and efficiency as keystone is stood up by its own servers. Users could have a separate key pair for the formPOST for extra security.

Blueprint information

Status:
Not started
Approver:
None
Priority:
Undefined
Drafter:
Venkat Sundaram
Direction:
Needs approval
Assignee:
Venkat Sundaram
Definition:
New
Series goal:
None
Implementation:
Unknown
Milestone target:
None

Related branches

Sprints

Whiteboard

Assumptions
the swift account id may or may not be the same as the project id in keystone
should not break existing customers of formPOST - should be backwards compatible
Proposal
The formPOST filter should change to re-construct data and leverage the generic signature validation filter. Thus, making it pluggable for future signing algorithms and implementations.

Pre-requisites:
generic signature validation filter should be setup to be used after this filter - this filter only re-constructs data for it
keystone account - the owner of the formPOST form should have an a/c with keystone with valid accessKey(s)
keystone tenant - the owner should pass their project ID and accessKey along with the formPOST... For project scoped access keys, only the access key needs to be passed along with the formPOST
High Level Design
The middleware components provides support for the following operations:

Parsing and processing information from the original REST request to form a generic signature validation request. Processing includes validating the signature expiry time.

Signature validation using the Keystone backend

Detailed Design
The formPOST filter should leverage the generic signature validation filter in the middleware filter chain. To achieve this, modify the existing Keystone client middleware formPOST filter as follows:

retain existing logic that parses the input and perform validation
extra parsing logic to get the signature algorithm used
detect formPOST style and use existing code to be backward compatible
construct data from the original formPOST signature in a way that is expected by the generic signature validation filter
set headers as required by the generic signature validation filter
pass the request down the filter chain bypassing the existing validation logic - as the filter down would do that
The fields that would be used for re-constructing data for the generic signature validation data:

Key Identifier
Data to sign
Algorithm
Signature value
Existing formPOST request received by swift middleware:
*Form data:*
<form action="<swift-url>" method="POST"
          enctype="multipart/form-data">
      <input type="hidden" name="redirect" value="<redirect-url>" />
      <input type="hidden" name="max_file_size" value="<bytes>" />
      <input type="hidden" name="max_file_count" value="<count>" />
      <input type="hidden" name="expires" value="<unix-timestamp>" />
      <input type="hidden" name="signature" value="<hmac>" />
      <input type="file" name="file1" /><br />
      <input type="submit" />
    </form>

where, *swift-url:* https://swift-cluster.example.com/v1/AUTH_account/container/object_prefix
Proposed formPOST request received by swift middleware:
*Form data:*
<form action="<swift-url>" method="POST"
          enctype="multipart/form-data">
      <input type="hidden" name="redirect" value="<redirect-url>" />
      <input type="hidden" name="max_file_size" value="<bytes>" />
      <input type="hidden" name="max_file_count" value="<count>" />
      <input type="hidden" name="expires" value="<unix-timestamp>" />
      <input type="hidden" name="signature" value="<tenant_id:access_key:signature_algorithm_name:signature>" />
      <input type="file" name="file1" /><br />
      <input type="submit" />
    </form>

where, *swift-url:* https://swift-cluster.example.com/v1/AUTH_account/container/object_prefix
Note: The form input field 'signature' will have the new additional info
Also, the fields "tenant_id","access_key" and "signature_algorithm_name" should be included when the signature is generated. This will ensure that these fields are not tampered with.

Payload to be re-constructed by formPOST filter:
{“auth”: {“identity”: {
“methods”: [“signature”],
“signature”: {
    “access_key_id”: access_key_id,
    “signature_method”: signature_alrogithm,
    “data_to_sign”: to_be_signed_data,
    “signature”: signature
 },
“scope”: scope_info
}
The Signature Validator then parses the signature validation response from the Keystone generic Signature Validation Service to builds the user headers that needs to be passed along to the next filter (Service Context Builder) in the pipeline

Classification:
To figure if the request is of old type or new, the following convention would be used:
formPOST-swift => this is the existing formPOST structure
formPOST-keystone => this would be the new formPOST as per keystone generic signature validation specifications

Identify formPOST type:
From the request form fields, figure if the request is formPOST-swift or formPOST-keystone
Classify as formPOST-swift if query params has only these fields:

redirect
max_file_size
max_file_count
expires
signature
file1
Further, parse the "signature" field and classify as formPOST-keystone, if the following parts are found:

signature_algorithm_name
tenant_id
access_key
Migrating existing formPOST customers:
update API documentation with details about the new formPOST structure and signing logic change
email customers about the new style of formPOST along with a list of keystone supported signature algorithms
specify a timeframe when formPOST-swift will be decommissioned
customer should find from their keystone a/c the following details
the project ID of the container
the accessKey/secretKey they wish to use
customer no longer need to set the X-Account-Meta-Temp-URL-Key header on their swift a/c
customer would user their preferred signature algorithm and sign the formPOST fields
customer would specify the formPOST-keystone fields specified above
should the customer need to invalidate the formPOST signature before the expiry time, they just need to revoke their accessKey using keystone

Gerrit topic: https://review.openstack.org/#q,topic:bp/formpost-middleware-change,n,z

Addressed by: https://review.openstack.org/57826
    formpost and tempurl validation with keystone.

Addressed by: https://review.openstack.org/69481
    formpost and tempurl validation with keystone.

(?)

Work Items

Dependency tree

* Blueprints in grey have been implemented.

This blueprint contains Public information 
Everyone can see this information.

Subscribers

No subscribers.