Skip to content

Commit

Permalink
Hoist report ID into upload request path
Browse files Browse the repository at this point in the history
Per httpdir early review of DAP ([1]), it's inappropriate to use PUT for
a resource that cannot later be GET. For that reason, and also
consistency with the aggregation job and collection job request paths,
hoist the report ID out of the upload request body and into the request
path. We don't want to repeat the report ID twice in one request, so
`struct Report` no longer includes a `struct Metadata` and instead just
puts the `time` inline in `Report`. `struct ReportMetadata` is still
used in `InputShareAad` and elsewhere in DAP, so its definition is not
changed, just moved farther down the document, and we explain how to
construct it from the report request path and body.

With this change, there is now a unique URI for each report uploaded to
a DAP leader. However we do not add any requirement that an Aggregator
support GET requests on that path, because not all DAP implementations
will necessarily store enough per-report information to be able to
respond to such a request with a complete `struct Report`.
Implementations are free to do that, but can also respond with HTTP 204,
404, 410 or some other error if they wish. As these are well-established
HTTP semantics, DAP doesn't need to spend any more ink on explaining
them.

[1]: https://datatracker.ietf.org/doc/review-ietf-ppm-dap-09-httpdir-early-nottingham-2023-12-29/
  • Loading branch information
tgeoghegan committed Jan 17, 2024
1 parent 3aee3f8 commit 571e7c6
Showing 1 changed file with 31 additions and 23 deletions.
54 changes: 31 additions & 23 deletions draft-ietf-ppm-dap.md
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,9 @@ the following parameters associated with it:
* A unique identifier for the VDAF in use for the task, e.g., one of the VDAFs
defined in {{Section 10 of !VDAF}}.

Note that the `leader_aggregator_url` and `helper_aggregator_url` values may
include arbitrary path components.

In addition, in order to facilitate the aggregation and collect protocols, each
of the Aggregators is configured with following parameters:

Expand Down Expand Up @@ -880,9 +883,12 @@ to the following rules:
value MUST be encoded in its URL-safe, unpadded Base 64 representation as
specified in {{Sections 5 and 3.2 of !RFC4648}}.

For example, resource URI `{leader}/tasks/{task-id}/reports` might be expanded
into
`https://example.com/tasks/8BY0RzZMzxvA46_8ymhzycOB9krN-QIGYvg_RsByGec/reports`
For example, given a leader URL "https://example.com/api/dap", task ID "f0 16 34
47 36 4c cf 1b c0 e3 af fc ca 68 73 c9 c3 81 f6 4a cd f9 02 06 62 f8 3f 46 c0 72
19 e7" and a report ID "95 ce da 51 e1 a9 75 23 68 b0 d9 61 f9 46 61 28" (32 and
16 byte octet strings, represented in hexadecimal), resource URI
`{leader}/tasks/{task-id}/reports/{report-id}` would be expanded into
`https://example.com/api/dap/tasks/8BY0RzZMzxvA46_8ymhzycOB9krN-QIGYvg_RsByGec/reports/lc7aUeGpdSNosNlh-UZhKA`.

## Uploading Reports {#upload-flow}

Expand Down Expand Up @@ -967,34 +973,27 @@ at least twice the cache lifetime in order to avoid rejecting reports.
### Upload Request

Clients upload reports by using an HTTP PUT to
`{leader}/tasks/{task-id}/reports`. The payload is a `Report`, with media type
"application/dap-report", structured as follows:
`{leader}/tasks/{task-id}/reports/{report-id}`. `report-id` is used by the
Aggregators to ensure the report appears in at most one batch (see
{{input-share-validation}}). The Client MUST generate this by sampling 16 bytes
from a cryptographically secure random number generator.

The payload is a `Report`, with media type "application/dap-report", structured
as follows:

~~~
struct {
ReportID report_id;
Time time;
} ReportMetadata;

struct {
ReportMetadata report_metadata;
opaque public_share<0..2^32-1>;
HpkeCiphertext leader_encrypted_input_share;
HpkeCiphertext helper_encrypted_input_share;
} Report;
~~~

* `report_metadata` is public metadata describing the report.

* `report_id` is used by the Aggregators to ensure the report appears in at
most one batch (see {{input-share-validation}}). The Client MUST generate
this by generating 16 random bytes using a cryptographically secure random
number generator.

* `time` is the time at which the report was generated. The Client SHOULD
round this value down to the nearest multiple of the task's
`time_precision` in order to ensure that that the timestamp cannot be used
to link a report back to the Client that generated it.
* `time` is the time at which the report was generated. The Client SHOULD
round this value down to the nearest multiple of the task's
`time_precision` in order to ensure that that the timestamp cannot be used
to link a report back to the Client that generated it.

* `public_share` is the public share output by the VDAF sharding algorithm. Note
that the public share might be empty, depending on the VDAF.
Expand Down Expand Up @@ -1054,19 +1053,28 @@ where `pk` is the Aggregator's public key; `0x01` represents the Role of the
sender (always the Client); `server_role` is the Role of the intended recipient
(`0x02` for the Leader and `0x03` for the Helper), `plaintext_input_share` is
the Aggregator's PlaintextInputShare, and `input_share_aad` is an encoded
message of type InputShareAad defined below, constructed from the same values as
the corresponding fields in the report. The `SealBase()` function is as
message of type InputShareAad defined below. The `SealBase()` function is as
specified in {{!HPKE, Section 6.1}} for the ciphersuite indicated by the HPKE
configuration.

~~~
struct {
ReportID report_id;
Time time;
} ReportMetadata;

struct {
TaskID task_id;
ReportMetadata report_metadata;
opaque public_share<0..2^32-1>;
} InputShareAad;
~~~

`report_metadata` is public metadata describing the report. `task_id` and
`report_metadata.report_id` are obtained from the corresponding values in the
upload request path. `report_metadata.time` and `public_share` are obtained from
the corresponding fields in the `Report`.

The Leader responds to well-formed requests with HTTP status code 201
Created. Malformed requests are handled as described in {{errors}}.
Clients SHOULD NOT upload the same measurement value in more than one report if
Expand Down

0 comments on commit 571e7c6

Please sign in to comment.