Subject: [CDNi] Benjamin Kaduk's Discuss on draft-ietf-cdni-uri-signing-24: (with DISCUSS and COMMENT)

From: Benjamin Kaduk via Datatracker <[email-masked]>
Date: Tue, 04 Jan 2022 08:22:14 -0800

Benjamin Kaduk has entered the following ballot position for
draft-ietf-cdni-uri-signing-24: Discuss

When responding, please keep the subject line intact and reply to all
email addresses included in the To and CC lines. (Feel free to cut this
introductory paragraph, however.)

Please refer to https://www.ietf.org/blog/handling-iesg-ballot-positions/
for more information about how to handle DISCUSS and COMMENT positions.

The document, along with other ballot positions, can be found here:
https://datatracker.ietf.org/doc/draft-ietf-cdni-uri-signing/

----------------------------------------------------------------------
DISCUSS:
----------------------------------------------------------------------

Thanks for the updates in the -22 through -24.  I think a couple of my
discuss points remain at the discuss level, which I'll expound on a bit more
below.

I am happy to see the pervasive disclaimers that use of a symmetric shared
key is supported but NOT RECOMMENDED, and the note that redistribution of
the symmetric shared key to dCDNs (including cascaded CDNs) is included for
legacy feature parity and highly discouraged in new implementations.
However, I think this does not fully address my original discuss point.  As
I said then, [[I see a minimal acknowledgment that there is potential cause
concern in the penultimate paragraph of the security considerations that "it
is important to know the implications of a compromised shared key", but in
my mind the text there does not really call out the severity of those
implications.  I would have expected something like "redistributing the
shared key in this manner allows the dCDNs to impersonate the CSP to the
uCDN and produce arbitrary signed URLs that are accepted by the uCDN as
authentic".]]  In particular, I think it is important to emphasize in some
manner that the cryptographc properties of the symmetric shared key are
fully symmetric across all participants, even though the administrative and
organizational structure here is hierarchical with explicitly more- and
less-trusted entities, making the symmetric cryptographic mechanism a
mismatch for the desired trust boundaries and inviting abuse.  Only
contractual controls prevent misuse in this scenario, whereas we have
well-understood technologies that allow technical measures to prevent misuse
that are preferred.

It's also still unclear to me that there's sufficient need to document the
symmetric key *redistribution* case in this document at all, if the only use
case is for "legacy feature parity".  Given that it's a fairly simple idea,
what is to stop us from leaving it undocumented in this Proposed Standard
and letting any implementors that need it do so on their own, or with a
separate Informational document mentioning its existence?  I am not aware of
any preexisting IETF work that we need to retain compatibility with, and the
data presented so far does not make a compelling (to me) case that we must
include this functionality in order for the IETF offering to be competitive.
(To be clear, I do not object to describing the use of symmetric keys for a
single-hop scenario, as the risks there are much smaller.)

I'd also like to have some additional discussion on this point from my
previous Discuss position, reproduced with typo fixed:
===
The combined defaults for the CDNI Metadata Interface for URI Signing seem
to be an unsafe combination.  Specifically, the default behavior for the
"issuers" property is to allow any Issuer, and the default for the
"jwt-header" property is to take the header from the JWT in band.  As far as
I can tell, this means that the dCDN will just blindly accept anything that
is formatted as a JWT and signed by any key known to the dCDN.  The
authentication and authorization properties of such behavior are so poor so
as to effectively be useless, absent some level of care surrounding key
management to isolate keys to given URIs.  In fact, the lack of substantive
discussion of key management and requirements thereof seems Discuss-worthy
in its own right.  We need to say something about obtaining a key along with
a trust path to what it's authorized to be used for, even if the specific
protocol mechanism for doing so is left out of scope.
===
I do see that §1.3 gained a mention of "obtain the key in a manner that
allows trust to be placed in the assertions made using that key", apparently
per my suggestion in my original COMMENT section.  However, I don't think
this is sufficient.  I strongly encourage a dedicated section on the
requirements for key management and how updates (both additions and
removals) of the list of trusted Issuer/key pairs are managed.  Failing
that, at a minimum the default for the "issuers" property in the CDNI
Metadata Interface needs to be changed to say that an empty list means that
any Issuer in the dCDN's trusted key store of issuers is acceptable for
signing JWTs for URI signing.  This is to be contrasted with "any Issuer at
all", which does not impose an obligation on the dCDN to maintain a list of
Issuer/key pairs trusted for signing JWTs used in signed URIs.

----------------------------------------------------------------------
COMMENT:
----------------------------------------------------------------------

Thanks for the updates to make use of "cdniip" NOT RECOMMENDED.  I'm still
uncomfortable about the way in which it is framed, but we have added enough
discussion of the risks it entails to make me demote it from being a
Discuss-level concern.

I'm also still uncomfortable about the directive to retain the same "jti"
value when re-signing in the redirection case, but in light of the input
from the IANA Designated Expert on the scope of potential harm from this
violation of RFC 7519, I have demoted that point from Discuss-level.

Thanks as well for adding the reference to RFC 8725, the JWT BCP.
I call attention to §3.11 thereof that recommends using explicit typing for
JWTs.  In the absence of evidence to the contrary, I believe that all new
JWT usage should include explicit type information; is there some reason why
explicit typing is not suitable here?

Thank you for acting on so many of my previous comments!  I think the
document is improved as a result.  I do retain some of my previous comments
that I didn't see any response to or changes as a result of, and have some
new comments interspersed as well.

Section 1.2

   before redirecting a UA to the CDN.  Using these attributes, it is
   possible for a CDN to check an incoming content request to see
   whether it was authorized by the CSP (e.g., based on the UA's IP
   address or a time window).  To prevent the UA from altering the

In light of cdniip being NOT RECOMMENDED, should the "UA's IP address" still
be mentioned in this parenthetical?

   the Target CDN URI itself is embedded in the HTML).  The Target CDN
   URI is the Signed URI which may include the IP address of the UA and/
   or a time window.  The signed URI always contains a signed JWT
   [...]
   JWT.  If applicable, the CDN checks whether the source IP address of
   the HTTP request matches the one in the Signed URI and/or if the time
   window is still valid.  [...]

Similarly, even if we may feel a need to include IP address in the
description here for completeness, we might want to shift the focus by
mentioning the more-recommended option first.

Section 2

   o  URI Signing Package (URISigningPackage): The URI attribute that
      encapsulates all the URI Signing claims in a signed JWT encoded
      format.  This attribute is exposed in the Signed URI as a path-
      style parameter or a form-style parameter.

Is there a good reference for "URI attribute"?  It sounds like should be
a technical term but I couldn't find a clear definition.

   The URI Signing Package will be found by parsing any path-style
   parameters and form-style parameters looking for a key name matching
   the URI Signing Package Attribute.  Both parameter styles MUST be
   supported to allow flexibility of operation.  The first matching
   parameter SHOULD be taken to provide the signed JWT, though providing
   more than one matching key is undefined behavior.  Path-style
   parameters generated in the form indicated by Section 3.2.7 of
   [RFC6570] MUST be supported.  Form-style parameters generated in the
   form indicated by Sections 3.2.8 and 3.2.9 of [RFC6570] MUST be
   supported.

The last two sentences seem a bit redundant with the second sentence
("Both parameter styles MUST be supported..."); it would be advisable to at
least use a lowercase "must" in the earlier sentence to avoid stating the
same normative requirement twice, if not just remove the redundant content
entirely.

Section 2.1

   The following claims (where the "JSON Web Token Claims" registry
   claim name is specified in parenthesis below) are used to enforce the
   distribution policies.  All of the listed claims are mandatory to
   implement in a URI Signing implementation, but are not mandatory to
   use in a given signed JWT.  (The "optional" and "mandatory"
   identifiers in square brackets refer to whether or not a given claim
   MUST be present in a URI Signing JWT.)

The final parenthetical suggests that the previous sentence should read
"not necessarily mandatory to use" (since apparently some of them *are*
mandatory to use).  Though I do see this was noted by Roman as well.  I
would be interested to hear why cdniuc is not mandatory (see below)...

   Note: The time on the entities that generate and verify the signed
   URI MUST be in sync.  In the CDNI case, this means that CSP, uCDN,
   and dCDN servers need to be time-synchronized.  It is RECOMMENDED to
   use NTP [RFC5905] for time synchronization.

I note that RFC 8915 presents Network Time Security for NTP, which might be
a helpful reference (and, arguably, worth recommending in its own right).
RFC 8633 is BCP 223, "Network Time Protocol Best Current Practices", also
worth referencing.

Section 2.1.x

[retained from my previous ballot position for posterity]
In general, my stance is that it's redundant to say that "the semantics
in Section X of RFC 7519 MUST be followed", because that's inherent in
the definition of the JWT claim.  But you're free to write the text as
you wish.

Section 2.1.1

   Issuer (iss) [optional] - The semantics in [RFC7519] Section 4.1.1
   MUST be followed.  If this claim is used, it MUST be used to confirm
   that the indicated key was provided by said issuer and used to sign
   the JWT.  [...]

I'm really confused at how these words fit together.  Is "the indicated key"
supposed to be a single unique key associated with the Issuer as identified
by the "iss" claim?  This is in general not true, as a given Issuer can have
more than one key in use.  Furthermore, what does it mean for the key to
have been "provided by" said issuer?  Provided when, as part of what
protocol flow?  If I ignore this sentence and just try to write something
based on my knowledge of JWT and expectations for how the CDNI URI Signing
works, I would write "If this claim is used, it MUST be used to identify the
issuer (signer) of the JWT.  In particular, the recipient will have already
received, in trusted configuration, a mapping of issuer name to one or more
keys used to sign JWTs, and must verify that the JWT was signed by one of
those keys."

             If the CDN verifying the signed JWT does not support Issuer
   verification, or if the Issuer in the signed JWT does not match the
   list of known acceptable Issuers, the CDN MUST reject the request.

I think this is intended to be "If this claim is used and the CDN verifying
the signed JWT [...]".

Also, I think this list also needs to include "if the Issuer claim does not
match the key used to sign the JWT".

Section 2.1.2

   Subject (sub) [optional] - The semantics in [RFC7519] Section 4.1.2
   MUST be followed.  If this claim is used, it MUST be a JSON Web
   Encryption (JWE [RFC7516]) Object in compact serialization form,
   because it contains personally identifiable information.  This claim

While I am happy to see that the subject information is recognized as
PII and required to be protected, it seems that this formulation is
over-constrained.  Why does the Subject specifically need to be
compact-serialization-form JWE, as opposed to some other encrypted form
(that cannot be correlated to other instances of the same encrypted
Subject?  Why does just using a signed-and-encrypted JWT for the
containing JWT not suffice?

   contains information about the subject (for example, a user or an
   agent) that MAY be used to verify the signed JWT.  If the received
   signed JWT contains a Subject claim, then any JWT subsequently
   generated for CDNI redirection MUST also contain a Subject claim, and
   the Subject value MUST be the same as in the received signed JWT.  [...]

Strict value equivalence seems problematic (given that we mandate
compact-form JWE), since there is a key (re)distribution problem for
making the information usable to any dCDN that is involved.  If it's
encrypted using a symmetric key, then the uCDN sharing it to the dCDN
introduces the same issue as for "signed" JWTs -- the dCDN can
impersonate the CSP; if it's using an asymmetric key then the set of
recipients is fixed at JWE creation (by the CSP) and we either lose the
ability to seamlessly add CDN tiers or have to redistribute the private
key (which is against best practices), in order to meet the "byte for
byte the same value" requirement.  What motivates the prohibition of
re-encrypting for the next level of hierarchy?  I think that in the JWT
convention we could say that the "the Subject identified by the value of the
'sub' claim in any JWT subsequently generated for CDNI redirection MUST be
the same as the Subject identified by the value of the 'sub' claim in the
received signed JWT" to achieve a requirement that the information content
remain unchanged, without requiring strict value equivalence.

Section 2.1.3

   Audience (aud) [optional] - The semantics in [RFC7519] Section 4.1.3
   MUST be followed.  This claim is used to ensure that the CDN
   verifying the JWT is an intended recipient of the request.  The claim
   MUST contain an identity on behalf of whom the CDN can verify the
   token (e.g., the CSP or any CDN in the chain).  A CDN MAY modify the
   claim as long it can generate a valid signature.

While a setup that naively translates JWT semantics to the CDNI case would
have the CSP issue a JWT with Audience of the uCDN (or some meta-Audience
for the combination of uCDN and dCDN), and then either the uCDN would
re-sign with the dCDN as the Audience or the dCDN would be configured to
recognize the Audience used by the CSP as being valid for itself, I think I
see what is intended here, that the CSP issues a JWT with Audience that
corresponds to the request as targeted to the CSP and ultimately ending up
at one or more CDNs.  That is, the CDNs know what CSP a given request is
supposed to come from, and can match the audience value against the CSP's
identification or an upstream CDN in addition to its own identification.  In
that case, I would suggest rewording to something like "The claim MUST
contain an identity belonging to the chain of entities involved in
processing the request (e.g., identifying the CSP or any CDN in the chain)
that the recipient is configured to use for the processing of this request".

Section 2.1.7

I think we need to make some statement (not necessarily here) about whether
the JWT ID used in JWTs issued by token renewal use the same or different
JWT IDs.  Currently we don't seem to say anything, and that seems likely to
lead to interoperability issues.

Section 2.1.9

It might be worth asking the OAuth WG if there's seen to be value in
having a generic "crit" claim that protocols can require comprehension
of, to hold a list of claims that are critical for that token in that
protocol.

Section 2.1.10

[same comments about encryption as for Subject]

Section 2.1.12

Can we give any guidance on what kind of values might make sense for the
CDNI Expiration Time Setting field and still providing some reasonable
security properties?  (Conversely, what kind of values are so large so
as to be nonsensical?)

Section 2.1.14

The first two paragraphs seem to talk about this claim as being a
direction to the client of when to send such a token along with a
request, but the third paragraph seems to talk about it as being a
direction to the CDN for generating new tokens as part of Signed Token
Renewal.  This leaves me confused about what the intended usage actually
is.

Section 2.1.15

   The URI Container (cdniuc) claim takes one of the following forms:
   'hash:' or 'regex:'.  More forms may be added in the future to extend
   the capabilities.

How will a JWT producer know whether a JWT consumer knows about any such
extended functionality?

Section 2.1.15.2

   An example of a 'regex:' is the following:

  [^:]*\\://[^/]*/folder/content/quality_[^/]*/segment.{3}\\.mp4(\\?.*)?

It seems a bit surprising to just do a wildcard match on scheme and
assume that the path components will be meaningful for that scheme.
Perhaps a variation that used branches to match only http or https
schemes would be preferred?

Section 4.4

      Property: issuers

         Description: A list of valid Issuers against which the Issuer
         claim in the signed JWT may be cross-referenced.

Cross-referencing or verifying against the JWT issuer is only part of
verifying a JWT; there needs to also be a binding between Issuer and key(s)
used to sign JWTs.  I think we should say something here about how the
Issuer/key binding is tracked, since it is apparently not part of the CDNI
metadata interface.

      Property: jwt-header

         Description: The header part of JWT that is used for verifying
         a signed JWT when the JWT token in the URI Signing Package does
         not contain a header part.

To me, "the header part of [a] JWT" would mean the base64-encoded version.
The example below uses a native JSON object.  I strongly suggest being more
precise about what this property is supposed to contain.  (Also,
RFC 8519 does not use the phrase "JWT header", and refers only to the "JOSE
header".)

   The following is an example of a URI Signing metadata payload with
   explicit values:

   {
     "generic-metadata-type": "MI.UriSigning"
     "generic-metadata-value":
       {
         "enforce": true,
         "issuers": ["csp", "ucdn1", "ucdn2"],

It might be more helpful to use the URI form of the Issuer names, since
in this generic RFC we do not have any deployment-specific context that
would allow the use of a short string issuer identifier.

Section 5.2

   2.   CSP provides to the uCDN the information needed to verify Signed
        JWTs from that CSP.  For example, this information will include
        one or more keys used for validation.

   3.   Using the CDNI Metadata interface, the uCDN communicates to a
        dCDN the information needed to verify Signed JWTs from the CSP
        [...]

Thanks for making changes so that the phrasing in this section more closely
matches the phrasing of the previous section!  It looks like the previous
section switched from "Signed JWTs" here to "signed URIs", so we might need
to catch up (twice).

Appendix A.3

   Once the server verifies the signed JWT it will return a new signed
   JWT with an updated expiry time (exp) as shown below.  Note the
   expiry time is increased by the expiration time setting (cdniets)
   value.

My previous comment was:
===
This example is adding the "cdniets" value to the previous "exp" value,
but the specification for this claim says that it is added to the "time
at which the JWT is verified", which is unlikely to be exactly the
previous "exp" value.  I suggest adding a few words about this and using
a different (earlier) "exp" in the re-signing example.
===
It looks like the update to use more-current "exp" values has caused the
"add the 'cdniets' value" step to be skipped, so that the two "exp" values
are identical.  I don't think they can actually be identical with "cdniets"
set to 30.

NITS

Section 1.2

   address or a time window).  To prevent the UA from altering the
   claims a JWT MUST be signed.

I think "the JWT" would flow better here.

Section 1.3

   routing.  Note that the signed Redirection URI MUST maintain HTTPS as
   the scheme if it was present in the original and it MAY be upgraded
   from HTTP to HTTPS.

When referring to URI schemes, we typically use the lower-case for "http:"
and "https:".

Section 2.1.9

   Its value is a comma separated listing of claims in the Signed JWT
   that use those extensions.  If any of the listed extension claims are

The causality seems reversed -- isn't it that the extensions use the claims
being marked critical, rather than the claims using the extensions?  So,
s/that use/that are used by/?

Section 2.1.15

      all other purposes will use the original URI.  If the signed JWT
      is terminated by anything other than a sub-delimiter (as defined
      in [RFC3986] Section 2.2), everything from the reserved character
      (as defined in [RFC3986] Section 2.2) that precedes the URI
      Signing Package Attribute to the last character of the signed JWT
      will be removed, inclusive.  Otherwise, everything from the first

Do we mean "immediately preceeds" here?

   *  Normalize the URI according to section 2.7.3 [RFC7230] and
      sections 6.2.2 and 6.2.3 [RFC3986].  This applies to both
      generation and verification of the signed JWT.

The HTTP spec is being revised, so Section 4.2.3 of
draft-ietf-httpbis-semantics may be a better reference than RFC 7230 here.

---

From: Phil Sorber <[email-masked]>
Date: Tue, 4 Jan 2022 17:38:39 -0700

Thank you for your very thorough review. I apologize for not responding to
your email directly last time and only making updates. I admit I was a bit
overwhelmed with the volume of your comments and struggled to get a full
response out. This time I am going to start off by addressing your discuss
points only and addressing your comments later.

> https://datatracker.ietf.org/doc/draft-ietf-cdni-uri-signing/

Thank you. I was trying to come up with some clear wording based on your
original comment, but could not. I do however like the extra text you have
added and will incorporate some form of that:
"the cryptographic properties of the symmetric shared key are
fully symmetric across all participants, even though the administrative and
organizational structure here is hierarchical with explicitly more- and
less-trusted entities, making the symmetric cryptographic mechanism a
mismatch for the desired trust boundaries and inviting abuse.  Only
contractual controls prevent misuse in this scenario, whereas we have
well-understood technologies that allow technical measures to prevent misuse
that are preferred."

> single-hop scenario, as the risks there are much smaller.)

We discussed this at our last meeting and then on the mailing list
afterward.

https://mailarchive.ietf.org/arch/msg/cdni/sDsFQnZqT0r7SOYTKu21CgPOwA8/

There was slightly more discussion in the meeting versus the mailing list
on this point. In fact, in the meeting it seemed we had agreed to remove
it, but then on the mailing list the feedback was marginally to keep it.

https://www.youtube.com/watch?v=0kwerjqOZ6I&t=2059s

I think the problem is just the realities of who is going to implement
this. I don't think someone wants to deduce how to get a feature they deem
necessary into their implementation, especially when someone else is
already providing them one that has it, albeit not standards compliant. So
the hope here is that we lower the bar to adoption and hope that as
interoperation grows people implement the asymmetric key model. Maybe that
is a naive approach. I definitely think it was not a cut and dry conclusion
to come to.

However, you do propose a scenario which I do not think we considered,
which is to keep shared key for the "single-hop" case, but remove the idea
of shared key distribution. I do not think that even current proprietary
implementations support the distribution aspect of it either. Let me
confirm this and if the WG is amenable to it, I will make that change.

> Issuer/key pairs trusted for signing JWTs used in signed URIs.

I will create a github PR with some proposed changes for this and get your
feedback on it. I feel like I understand and agree with your statement, but
I am failing to change the text to the level you feel it needs to be at.

> _______________________________________________
> CDNi mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/cdni
>

---

From: Benjamin Kaduk <[email-masked]>
Date: Thu, 6 Jan 2022 14:19:48 -0800

Hi Phil,

> points only and addressing your comments later.

I confess that sometimes I am overwhelmed when the reply comes back to me,
and end up taking a week or two to be able to process it.
Starting off with just the discuss points is a great plan. (inline)

> well-understood technologies that allow technical measures to prevent misuse

Feel free to chop up, rearrange, rewrite, or do what you want with that
text, if it helps.

> confirm this and if the WG is amenable to it, I will make that change.

Oh!  I am sorry to have not been more clear previously -- my strenuous
objection is solely to the aspect where the same key is shared by CSP,
uCDN, and dCDN (or analogous uCDN/middle-CDN/dCDN cases).  In that scenario
the uCDN is at risk of having a compromised or malicious dCDN pretend to be
the CSP, and the relationship between uCDN and CSP is vastly different than
its relationship with dCDN, so the potential "privilege escalation" for the
dCDN is huge.

Using a symmetric key just between CSP and uCDN, or uCDN and dCDN, is still
not the best choice, but (as you note) it's widely deployed and the risks
are much more manageable.  In particular, with only the "two-party" case,
the harm from compromise of one party is mostly limited to affecting that
same party, as opposed to the situation I mentioned earlier where dCDN
compromise causes harm to the CSP (in that the uCDN thinks something came
from the CSP but actually it did not).

If we can get WG agreement to just remove the shared-key redistribution
aspect, that seems like a very workable resolution.

> I am failing to change the text to the level you feel it needs to be at.

Okay, that sounds good.  Feel free to tag me in (@kaduk), though I get a
lot of github notifications, so I might not see it right away.

Thanks,

Ben