From 9157ce2e2b1cfc40261cbc9fe9ce418854681ea4 Mon Sep 17 00:00:00 2001 From: Ian Clelland Date: Wed, 18 Dec 2019 14:16:45 -0500 Subject: [PATCH 1/6] Switch reporting to structured headers --- index.src.html | 160 +++++++++++++++++++------------------------------ 1 file changed, 61 insertions(+), 99 deletions(-) diff --git a/index.src.html b/index.src.html index 171eaab..480202b 100644 --- a/index.src.html +++ b/index.src.html @@ -131,6 +131,9 @@

Reporting API

text: session; url: dfn-session text: success; url: dfn-success text: trying; url: dfn-try +spec: STRUCTURED-HEADERS; urlPrefix: https://httpwg.org/http-extensions/draft-ietf-httpbis-header-structure.html# + type: grammar + text: sh-dictionary; url: rfc.section.3.2
 {
@@ -139,6 +142,12 @@ 

Reporting API

"href": "https://w3c.github.io/webappsec-secure-contexts/", "title": "Secure Contexts", "publisher": "W3C" + }, + "STRUCTURED-HEADERS": { + "authors": [ "Mark Nottingham", "Poul-Henning Kamp" ], + "href": "https://httpwg.org/http-extensions/draft-ietf-httpbis-header-structure.html", + "title": "Structured Headers for HTTP", + "publisher": "IETF" } } @@ -192,11 +201,8 @@

Examples

define a set of reporting endpoints named "`endpoint-1`":
-      Report-To: { "group": "endpoint-1",
-                   "endpoints": [
-                     { "url": "https://example.com/reports", "priority": 1 },
-                     { "url": "https://backup.com/reports", "priority": 2 }
-                   ] }
+      Report-To: endpoint-1=("https://example.com/reports";priority=1
+                                    "https://backup.com/reports";priority=2)
     
And the following headers, which direct CSP and HPKP reports to that group: @@ -214,14 +220,9 @@

Examples

the following header to define two reporting endpoints:
-      Report-To: { "group": "csp-endpoint",
-                   "endpoints": [
-                     { "url": "https://example.com/csp-reports" }
-                   ] },
-                 { "group": "hpkp-endpoint",
-                   "endpoints": [
-                     { "url": "https://example.com/hpkp-reports" }
-                   ] }
+      Report-To: csp-endpoint=("https://example.com/csp-reports";priority=1
+                                      "https://backup.com/csp-reports";priority=2),
+                        hpkp-endpoint=("https://example.com/hpkp-reports")
     
And the following headers, which direct CSP and HPKP reports to those named @@ -514,8 +515,8 @@

Document configuration

Each document has an endpoint-groups list, which is a list of endpoint groups, each of which MUST have a distinct {{endpoint group/name}}. - (The algorithm in [[#process-header]] guarantees this by keeping the first - entry in a `Report-To` header with a particular name.) + (The parsing algorithm for dictionaries in [[STRUCTURED-HEADERS]] enforces + this by failing to parse a dictionary with duplicated keys.) A server MAY define a set of reporting endpoints for a resource it returns, via the `Report-To` HTTP response header field. This mechanism @@ -527,43 +528,12 @@

Document configuration

The value of the `Report-To` HTTP response header field is - used to construct the reporting configuration for a resource. The header is - represented by the following ABNF grammar [[!RFC5234]]: - -
-    Report-To = json-field-value
-                ; See Section 2 of [[HTTP-JFV]], and Section 2 of [[RFC8259]]
-  
- - The header's value is interpreted as a JSON-formatted array of objects - without the outer `[` and `]`, as described in Section 4 of [[HTTP-JFV]]. - - Each object in the array defines an endpoint group to which reports may - be delivered, and will be parsed as defined in [[#process-header]]. - - The following subsections define the initial set of known members in each - JSON object the header's value defines. Future versions of this document may - define additional such members, and user agents MUST ignore unknown members - when parsing the header. - -

The `group` member

- - The OPTIONAL `group` member is a string that - associates a {{endpoint group/name}} with the endpoint group. The - member's value MUST be a string; any other type will result in a parse - error. If no member named "`group`" is present in the object, the endpoint - group will be given the {{endpoint group/name}} "`default`". + used to construct the reporting configuration for a resource. -

The `endpoints` member

- - The REQUIRED `endpoints` member defines the - list of endpoints that belong to this endpoint - group. The member's value MUST be an array of JSON objects. - - The following subsections define the initial set of known members in each JSON - object in the array. Future versions of this document may define additional - such members, and user agents MUST ignore unknown members when parsing the - elements of the array. + `Report-To` is a Dictionary Structured Header [[STRUCTURED-HEADERS]]. + Each entry in the dictionary defines an endpoint group to which reports + may be delivered. The entry value MUST be an inner-list, whose members are + endpoints. -

The `endpoints.url` member

- - The REQUIRED `url` member is a string that defines - the location of the endpoint. The member's value MUST be a string; any - other type will result in a parse error. + Each endpoint is defined by a String Item, which is interpreted as a + URI-reference. If its value is not a valid URI-reference, that endpoint + member MUST be ignored. Moreover, the URL that the member's value represents MUST be potentially trustworthy [[!SECURE-CONTEXTS]]. Non-secure endpoints will be ignored. -

The `endpoints.priority` member

+ The following parameters are defined for endpoints: + + * "priority", whose value is an integer, which defines which failover class + the endpoint belongs to. The parameter's value, if present, MUST be + non-negative; other values MUST cause the entire endpoint to be ignored. - The OPTIONAL `priority` member is a number that - defines which failover class the endpoint belongs to. The member's - value, if present, MUST be a non-negative integer; any other type will result - in a parse error. + * "weight", whose value is an integer, which defines load balancing for the + failover class that the endpoint belongs to. The parameter's value, + if present, MUST be non-negative; other values MUST cause the entire + endpoint to be ignored. -

The `endpoints.weight` member

+ The header is represented by the following ABNF grammar [[!RFC5234]]: - The OPTIONAL `weight` member is a number that - defines load balancing for the failover class that the endpoint belongs - to. The member's value, if present, MUST be a non-negative integer; any other - type will result in a parse error. +
+    Report-To = sh-dictionary
+  

Process reporting endpoints for |response| @@ -621,57 +592,48 @@

header in |response|'s header list whose name is "`Report-To`". - 3. Let |list| be the result of executing the algorithm defined in Section 4 - of [[HTTP-JFV]] on |header|. If that algorithm results in an error, abort - these steps. + 3. Let |parsed header| be the result of executing the algorithm defined in + Section 4.2 of [[STRUCTURED-HEADERS]] on |header|, with header_type set to "dictionary". If that algorithm fails + parsing, abort these steps. 4. Let |groups| be an empty list. - 5. For each |item| in |list|: - - 1. If |item| has no member named "`endpoints`", or that member's - value is not an array, skip to the next |item|. - - 2. Let |name| be |item|'s "`group`" member's value - if present, and "`default`" otherwise. + 5. For each |name| → |value_and_parameters| of |parsed header|: - 3. If there is already an endpoint group in |groups| whose - {{endpoint group/name}} is |name|, skip to the next |item|. + 1. Let |value| be the first element of the tuple |value_and_parameters|. + If |value| is not an array, then continue. - 4. Let |endpoints| be an empty list. + 2. Let |endpoints| be an empty list. - 5. For each |endpoint item| in the value of |item|'s "`endpoints`" member: + 3. For each |endpoint item| of |value|: - 1. If |endpoint item| has no member named "`url`", or that member's value is not a - string, or if that value is not an absolute-URL string or a + 1. Let |endpoint url| and |endpoint parameters| be the elements of + the tuple |endpoint item|. If |endpoint url| is not a string, or + if that value is not an absolute-URL string or a path-absolute-URL string, skip to the next |endpoint item|. - 2. If |endpoint item| has a member named "`priority`", whose value is not a non-negative - integer, skip to the next |endpoint item|. + integer, then continue. - 3. If |endpoint item| has a member named "`weight`", whose value is not a non-negative - integer, skip to the next |endpoint item|. + integer, then continue. 4. Let |endpoint| be a new endpoint whose properties are set as follows: : {{endpoint/url}} :: The result of executing the URL parser on - |endpoint item|'s "`url`" member's - value, with base URL set to |response|'s url. + |endpoint url|, with base URL set to + |response|'s url. : {{endpoint/priority}} - :: The value of the |endpoint item|'s "`priority`" member, if present; `1` - otherwise. + :: The value of |endpoint parameters|["`priority`"], if it exists; `1` otherwise. : {{endpoint/weight}} - :: The value of the |endpoint item|'s "`weight`" member, if present; `1` - otherwise. + :: The value of |endpoint parameters|["`weight`"], if it exists; `1` otherwise. : {{endpoint/failures}} :: 0 : {{endpoint/retry_after}} @@ -679,7 +641,7 @@

5. Add |endpoint| to |endpoints|. - 6. Let |group| be a new endpoint group whose properties are + 4. Let |group| be a new endpoint group whose properties are set as follows: : {{endpoint group/name}} @@ -687,7 +649,7 @@

: {{endpoint group/endpoints}} :: |endpoints| - 7. Add |group| to |groups|. + 5. Add |group| to |groups|. 6. Return |groups|. From a752bd8067fad697f1f5d92c6e9ad79911594ddd Mon Sep 17 00:00:00 2001 From: Ian Clelland Date: Fri, 10 Jan 2020 16:24:20 -0500 Subject: [PATCH 2/6] Add structured-headers to topic branches --- deploy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy.sh b/deploy.sh index c93509b..5751605 100644 --- a/deploy.sh +++ b/deploy.sh @@ -11,7 +11,7 @@ TARGET_BRANCH="gh-pages" # List of long-lived topic branch names to be published on github.io as a # subdirectory -TOPIC_BRANCHES=("split-persistence") +TOPIC_BRANCHES=("split-persistence structured-headers") containsElement () { local e match="$1" From 891d5e105eafbdc5eea16a7825bda8a1115f5b21 Mon Sep 17 00:00:00 2001 From: Ian Clelland Date: Fri, 10 Jan 2020 16:30:18 -0500 Subject: [PATCH 3/6] Fix topic branch config --- deploy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy.sh b/deploy.sh index 5751605..0f71d0a 100644 --- a/deploy.sh +++ b/deploy.sh @@ -11,7 +11,7 @@ TARGET_BRANCH="gh-pages" # List of long-lived topic branch names to be published on github.io as a # subdirectory -TOPIC_BRANCHES=("split-persistence structured-headers") +TOPIC_BRANCHES=("split-persistence" "structured-headers") containsElement () { local e match="$1" From 324b17e2198df145f86c73504eec1087613d026f Mon Sep 17 00:00:00 2001 From: Ian Clelland Date: Mon, 13 Jan 2020 14:26:05 -0500 Subject: [PATCH 4/6] Remove reference to 'URI-reference' --- index.src.html | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/index.src.html b/index.src.html index 8a620b9..5b30c70 100644 --- a/index.src.html +++ b/index.src.html @@ -526,8 +526,8 @@ --> Each endpoint is defined by a String Item, which is interpreted as a - URI-reference. If its value is not a valid URI-reference, that endpoint - member MUST be ignored. + URI-reference. If its value is not an absolute-URL string or a + path-absolute-URL string, that endpoint member MUST be ignored. Moreover, the URL that the member's value represents MUST be potentially trustworthy [[!SECURE-CONTEXTS]]. Non-secure endpoints will be ignored. @@ -592,26 +592,30 @@

3. For each |endpoint item| of |value|: - 1. Let |endpoint url| and |endpoint parameters| be the elements of - the tuple |endpoint item|. If |endpoint url| is not a string, or - if that value is not an absolute-URL string or a + 1. Let |endpoint url string| and |endpoint parameters| be the + elements of the tuple |endpoint item|. If |endpoint url| is not a + string, or if that value is not an absolute-URL string or a path-absolute-URL string, skip to the next |endpoint item|. - 2. If |endpoint parameters| has a member named "URL parser on |endpoint url string|, with base URL set to |response|'s url. If |endpoint url| is failure, skip to the next + |endpoint item|. + + 3. If |endpoint parameters| has a member named "`priority`", whose value is not a non-negative integer, then continue. - 3. If |endpoint parameters| has a member named "`weight`", whose value is not a non-negative integer, then continue. - 4. Let |endpoint| be a new endpoint whose properties are set + 5. Let |endpoint| be a new endpoint whose properties are set as follows: : {{endpoint/url}} - :: The result of executing the URL parser on - |endpoint url|, with base URL set to - |response|'s url. + :: |endpoint url| : {{endpoint/priority}} :: The value of |endpoint parameters|["`priority`"], if it exists; `1` otherwise. @@ -623,7 +627,7 @@

: {{endpoint/retry_after}} :: `null` - 5. Add |endpoint| to |endpoints|. + 6. Add |endpoint| to |endpoints|. 4. Let |group| be a new endpoint group whose properties are set as follows: From c1b4c3d962747e4855006e5033d29c7b7062457c Mon Sep 17 00:00:00 2001 From: Ian Clelland Date: Wed, 5 Feb 2020 15:59:31 -0500 Subject: [PATCH 5/6] Rename header --- index.src.html | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/index.src.html b/index.src.html index 32b838a..0c8e17c 100644 --- a/index.src.html +++ b/index.src.html @@ -176,7 +176,7 @@

Examples

define a set of reporting endpoints named "`endpoint-1`":
-      Report-To: endpoint-1="https://example.com/reports"
+      Reporting-Endpoints: endpoint-1="https://example.com/reports"
     
And the following headers, which direct CSP and HPKP reports to that @@ -195,8 +195,8 @@

Examples

the following header to define two reporting endpoints:
-      Report-To: csp-endpoint="https://example.com/csp-reports",
-                        hpkp-endpoint="https://example.com/hpkp-reports"
+      Reporting-Endpoints: csp-endpoint="https://example.com/csp-reports",
+                           hpkp-endpoint="https://example.com/hpkp-reports"
     
And the following headers, which direct CSP and HPKP reports to those named @@ -399,23 +399,25 @@

Document configuration

attribute>endpoints list, which is a list of endpoints, each of which MUST have a distinct {{endpoint/name}}. (The algorithm in [[#process-header]] guarantees this by keeping the first entry in a - `Report-To` header with a particular name.) + `Reporting-Endpoints` header with a particular name.) A server MAY define a set of reporting endpoints for a resource it returns, - via the `Report-To` HTTP response header field. This mechanism - is defined in [[#header]], and its processing in [[#process-header]]. + via the `Reporting-Endpoints` HTTP response header field. This + mechanism is defined in [[#header]], and its processing in + [[#process-header]]. Each document has an reports list, which is a list of reports. - + - The value of the `Report-To` HTTP response header field is - used to construct the reporting configuration for a resource. + The value of the `Reporting-Endpoints` HTTP response header + field is used to construct the reporting configuration for a resource. - `Report-To` is a Dictionary Structured Header [[STRUCTURED-HEADERS]]. - Each entry in the dictionary defines an endpoint to which reports may - be delivered. The entry value MUST be a string. + `Reporting-Endpoints` is a Dictionary Structured Header + [[STRUCTURED-HEADERS]]. Each entry in the dictionary defines an + endpoint to which reports may be delivered. The entry value MUST be a + string. Each endpoint is defined by a String Item, which is interpreted as a URI-reference. If its value is not a valid URI-reference, that endpoint @@ -430,7 +432,7 @@ The header is represented by the following ABNF grammar [[!RFC5234]]:
-    Report-To = sh-dictionary
+    Reporting-Endpoints = sh-dictionary
   

@@ -454,11 +456,11 @@

2. |response|'s header list does not contain a header whose name is - "`Report-To`". + "`Reporting-Endpoints`". 2. Let |header| be the value of the header in |response|'s header list - whose name is "`Report-To`". + whose name is "`Reporting-Endpoints`". 3. Let |parsed header| be the result of executing the algorithm defined in Section 4.2 of [[STRUCTURED-HEADERS]] on |header|, with Disabling Reporting

IANA Considerations

-

The `Report-To` Header

+

The `Reporting-Endpoints` Header

The permanent message header field registry should be updated with the following registration: [[!RFC3864]] : Header field name - :: `Report-To` + :: `Reporting-Endpoints` : Applicable protocol :: http : Status From 6497ff55735f645bfda9133ba1e657dcc2c896ec Mon Sep 17 00:00:00 2001 From: Ian Clelland Date: Mon, 10 Feb 2020 16:09:30 -0500 Subject: [PATCH 6/6] Remove URL productions --- index.src.html | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/index.src.html b/index.src.html index 0c8e17c..b8d60ac 100644 --- a/index.src.html +++ b/index.src.html @@ -473,16 +473,18 @@

1. Let |endpoint url string| be the first element of the tuple - |value_and_parameters|. If |endpoint url string| is not a string, or - if that value is not an absolute-URL string or a - path-absolute-URL string, then continue. + |value_and_parameters|. If |endpoint url string| is not a string, + then continue. 2. Let |endpoint url| be the result of executing the URL parser on |endpoint url string|, with base URL set to |response|'s url. If |endpoint url| is failure, then continue. - 3. Let |endpoint| be a new endpoint whose properties are set + 3. If |endpoint url|'s origin is not potentially + trustworthy, then continue. + + 4. Let |endpoint| be a new endpoint whose properties are set as follows: : {{endpoint/name}} @@ -492,7 +494,7 @@

: {{endpoint/failures}} :: 0 - 4. Add |endpoint| to |endpoints|. + 5. Add |endpoint| to |endpoints|. 6. Return |endpoints|.