diff --git a/pipeline-specification/features/evidence.md b/pipeline-specification/features/evidence.md index e222808..44e824a 100644 --- a/pipeline-specification/features/evidence.md +++ b/pipeline-specification/features/evidence.md @@ -15,6 +15,15 @@ Currently, defined examples of keys are: - `cookie.[cookie-name]` [^1] - `server.client-ip` - `server.host-ip` +- `server.request-method` +- `server.request-path` +- `server.request-query` + +The three `server.request-` keys carry the request line exactly as it +was sent, byte for byte with no decoding, because signature +verification rebuilds covered parts of the request exactly. See +[web integration](web-integration.md#populating-evidence) for the +detail. Any new Evidence keys can be defined in a similar manner. diff --git a/pipeline-specification/features/web-integration.md b/pipeline-specification/features/web-integration.md index 44bb81a..76beafd 100644 --- a/pipeline-specification/features/web-integration.md +++ b/pipeline-specification/features/web-integration.md @@ -73,6 +73,29 @@ and the Evidence names they would be associated with. - Public client IP. Key is `server.client-ip` - Request protocol. Can come from the request itself or headers such as `X-Origin-Proto` or `X-Forwarded-Proto`. Key is `header.protocol` +- Request method. Key is `server.request-method` +- Request path. Key is `server.request-path` +- Request query string, whole and undecoded. Key is `server.request-query` + +The three request line values (`server.request-method`, +`server.request-path` and `server.request-query`) MUST be supplied +exactly as they appeared on the request line, byte for byte, with no +decoding and no normalisation. The +[Agent Signature Element](../pipeline-elements/agent-signature-element.md) +rebuilds the parts of a request that a signature covers and checks the +signature against the rebuilt text, so one changed byte makes a valid +signature read as invalid. This is also why the query string is carried +whole under `server.request-query` as well as decoded into the +`query.[parameter name]` pairs, because the decoded pairs lose the +ordering and encoding of the original and cannot rebuild it. An +integration that supplies these keys MUST supply all three on every +request, with `server.request-query` empty when the request has no +query string, so that an absent key always means the integration does +not supply the request line rather than that the request had no query. +A web integration that populates Evidence through the Pipeline's +[accepted Evidence](advertize-accepted-evidence.md) feature only adds +these values when an element in the Pipeline asks for them, so a +Pipeline without such an element carries no new values. ## Setting response headers diff --git a/pipeline-specification/pipeline-elements/agent-signature-element.md b/pipeline-specification/pipeline-elements/agent-signature-element.md index f881383..bb9df69 100644 --- a/pipeline-specification/pipeline-elements/agent-signature-element.md +++ b/pipeline-specification/pipeline-elements/agent-signature-element.md @@ -318,9 +318,20 @@ strict form, such as one writing a space after a parameter semicolon. IPv6 address is, keeps its brackets and only a port after the closing bracket is removed. - `@scheme` is the value of `header.protocol` lowercased. -- `@target-uri`, `@method`, `@path` and `@query` cannot be rebuilt, because - the request line is not in the Evidence today. A signature covering any of - them reports Unverified with reason `ComponentUnavailable`. +- `@method` is the value of `server.request-method`. `@path` is the value + of `server.request-path`. `@query` is the value of + `server.request-query` with a leading `?` added, and where the key is + present with an empty value the component is `?` alone, as RFC 9421 + section 2.2.7 requires. `@target-uri` is assembled from the scheme, the + authority, the path and the query. These four Evidence keys are defined + in [web integration](../features/web-integration.md#populating-evidence), + and the values are the request line byte for byte, because one changed + byte makes a valid signature read as invalid. Where a covered component + names an Evidence key the request does not carry, the signature reports + Unverified with reason `ComponentUnavailable`, which is also the answer + in an implementation whose web integration does not yet supply the + request line (the .NET web integration does not today, tracked in + [pipeline-dotnet #374](https://github.com/51Degrees/pipeline-dotnet/issues/374)). A signature covering `@authority` and `signature-agent`, which is what the protocol draft's own example and the published test vectors do, can always