<?xml version="1.0" encoding="utf-8"?>
<?xml-model href="rfc7991bis.rnc"?> 


<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>

<rfc
  xmlns:xi="http://www.w3.org/2001/XInclude"
  category="std"
  consensus="true"
  ipr="trust200902"
  obsoletes=""
  updates=""
  submissionType="IETF"
  xml:lang="en"
  version="3"
  tocInclude="true"
  tocDepth="5"
  symRefs="true"
  sortRefs="true"
  docName="draft-ietf-cdni-edge-control-metadata-11"
>
   <front>
      <title abbrev="CDNI Edge Control Metadata">CDNI Edge Control Metadata</title>
      <author initials="A." surname="Siloniz" fullname="Alfonso Siloniz">
         <organization>Telefonica</organization>
         <address>
            <postal>
               <street />
               <city />
               <region />
               <code />
               <country>Spain</country>
            </postal>
            <email>alfonsosiloniz@gmail.com</email>
         </address>
      </author>      
      <author fullname="Glenn Goldstein" initials="G." surname="Goldstein">
         <organization>Lumen Technologies</organization>
         <address>
            <postal>
               <street />
               <city />
               <region />
               <code />
               <country>US</country>
            </postal>
            <email>glenng1215@gmail.com</email>
         </address>
      </author>
      <date />
      <workgroup>Content Delivery Networks Interconnection</workgroup>
      <abstract>
         <t>
This specification defines configuration metadata objects used to manage how edge servers control access to resources within Content Delivery Networks (CDNs) and Open Caching systems. A key feature of these configurations is the configuring of Cross-Origin Resource Sharing (CORS) access rules and the dynamic generation of CORS headers. This specification also provides the ability to define response body compression rules and client connection timeouts.
        </t>
      </abstract>
   </front>
<middle>
<section anchor="h.3znysh7">
  <name>Introduction</name>
  <t>CDNs and Open Caching systems <xref target="OC"/> typically require a set of configuration metadata to provide directives for processing responses downstream (at the edge and in the user agent). This document specifies GenericMetadata objects to meet those requirements, defining edge processing rules such as Cross-Origin Resource Sharing (CORS) handling, response compression, and client connection failures.</t>
</section><section anchor="requirements" title="Requirements">
<t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in <xref target="RFC2119"/>.</t>
</section><section anchor="h.j0bxom85rm4">
  <name>MI.CrossoriginPolicy</name>
  <section anchor="h.9wkccrtrfh91">
    <name>Overview</name>
    <t>When a user interacts with a Content Provider (CP) application, such as a streaming app on a smartphone or a web browser, the device initiates a request for content distributed by a CDN. This process typically begins with an initial request to the CP's URL using a Fully Qualified Domain Name (FQDN) within the CP's own domain. Depending on the CDN architecture, the response may trigger an HTTP redirection to a different FQDN, usually one belonging to the CDN's domain. While this transition is necessary for delivery, many User Agents apply strict 'same-origin' security restrictions to these network requests, which can block the content unless specific access rules are defined.</t>
    <t>Cross-origin resource sharing (CORS) is a protocol that allows a HTTP client application to access restricted resources from a server on a domain different from the domain that served the original request. It is defined by the Web Hypertext Application Technology Working Group (WHATWG) Fetch Living Standard <xref target="WHATWG-FETCH"/>.</t>
    <t>CORS is based on HTTP request and response headers, which must be managed appropriately.</t>
    <t>For clarification, it is important to note that the concept of an Origin in the CDN context is different from that in the CORS context. The former indicates the source from where the CDN acquires content (the Origin Server), while the latter identifies the security context (scheme, host, and port) of the web application making the request.</t>
    <t>To permit shared cross-origin network requests, CORS protocol defines a set of request and response headers that must be present to permit access to these restricted resources. Two situations can occur when one or more CDNs are involved in processing these requests:</t>
    <ul>
      <li>
        <t>CDNs forward the User-Agent (UA) request headers to the CP servers, and they forward the response headers generated back to the UA.</t>
      </li>
      <li>
        <t>CDNs can include logic to dynamically generate the required response headers based on the UA request without contacting the CP servers.</t>
      </li>
    </ul>
    <t>The dynamic generation of CORS headers is typical in modern HTTP request processing and avoids forwarding CORS headers to the uCDN, thereby reducing the load between dCDN and uCDN when the content to be delivered is already cached in the dCDN. </t>
    <t>Also consider that there are two types of requests involved in the CORS protocol as defined in Section 3.2.2 of <xref target="WHATWG-FETCH"/>:</t>
    <ul>
      <li>
        <t>A CORS request is any HTTP request that includes an Origin header. The Origin header is a version of the Referer header that does not reveal a path, as defined in Section 3.1 of <xref target="WHATWG-FETCH"/></t>
      </li>
      <li>
        <t>A CORS preflight request is a CORS request to check whether the CORS protocol is understood by the delivery server, and to ensure that it includes valid CORS response headers. It uses the OPTIONS method along with some other specific request headers to indicate which method and headers will be used in a future CORS request to the same resource.</t>
      </li>
    </ul>
    <t>The CDN Interconnection (CDNI) metadata model requires extensions to permit a uCDN to declare how a dCDN MUST evaluate and dynamically generate the necessary CORS response headers, avoiding the forwarding of CORS requests and/or preflight requests to the uCDN.</t>
    <t>Required capabilities:</t>
    <ul>
      <li>
        <t>Set a default value for CORS response headers independent of the value of the Origin request header.</t>
      </li>
      <li>
        <t>Match the value of the Origin request header with a list of valid values. If it is successful, the dCDN will inject the appropriate CORS response headers. </t>
      </li>
      <li>
        <t>Set a list of custom response headers that are allowed to be exposed to the client using  CORS response headers.</t>
      </li>
      <li>
        <t>Dynamically generate CORS response headers to CORS preflight requests including custom header validation, expose headers, and methods.</t>
      </li>
      <li>
        <t>Support credentials validation within CORS.</t>
      </li>
    </ul>
  </section>
  <section anchor="h.n0zup5hamydu">
    <name>dCDN Required behavior</name>
    <t>The dCDN MUST implement the following behavior as determined by the GenericMetadata object <xref target="h.e1lhw0cdqlzq">MI.CrossoriginPolicy</xref> defined in this section:</t>
    <ul>
      <li>
        <t>Validation of the Origin request header - If <xref target="h.e1lhw0cdqlzq">MI.CrossoriginPolicy</xref> defines a list of domains to validate,  if the Origin request header does not match, the CORS response headers MUST NOT be included in the dCDN response. UA compliance with Section 3.3 of <xref target="WHATWG-FETCH"/> with "same-origin" restrictions will prevent access to the resource.</t>
      </li>
      <li>
        <t>Wildcard usage - If the Origin request header is valid, depending on the configuration, the value of the CORS response header to include in the response will be the same as the Origin request header, or a wildcard. </t>
      </li>
      <li>
        <t>uCDN is able to configure a list of default values for CORS response headers in <xref target="h.e1lhw0cdqlzq">MI.CrossoriginPolicy</xref> Generic Metadata object that dCDN MUST add if present independent of the value of the Origin request header.</t>
      </li>
      <li>
        <t>If the UA is expected to use CORS preflight requests, uCDN can also configure the dCDN to dynamically generate synthetic responses to HTTP OPTIONS method requests as defined in Section 3.3.2 of <xref target="WHATWG-FETCH"/></t>
      </li>
    </ul>
    <t>When an uCDN configures one or more of the expose-headers, allow-methods, allow-headers, allow-credentials and max-age properties the dCDN MUST generate synthetic responses to any CORS preflight request without contacting the uCDN servers. In this case the dCDN will add the corresponding CORS response headers to every non-empty parameter. </t>
    <t>If none of those parameters are set in the configuration, the dCDN MUST forward every CORS preflight request (OPTIONS method) to the uCDN servers and process their responses before responding to the UAs.</t>
  </section>
  <section anchor="h.e1lhw0cdqlzq">
    <name>MI.CrossoriginPolicy</name>
    <t>MI.CrossoriginPolicy is a GenericMetadata object that allows configuring dynamically generated CORS headers.</t>
    <t> </t>
    <t>Property: allow-origin</t>
    <ul>
      <li>
        <t>Description: Validation of simple CORS requests.</t>
      </li>
      <li>
        <t>Type: Object <xref target="h.4bkljf3s2m4a">MI.AccessControlAllowOrigin</xref></t>
      </li>
      <li>
        <t>Mandatory-to-Specify: Yes</t>
      </li>
    </ul>
    <t>Property: expose-headers</t>
    <ul>
      <li>
        <t>Description: A list of header names the dCDN will include in the Access-Control-Expose-Headers response header of a CORS preflight request.</t>
      </li>
      <li>
        <t>Type: Array of Field Names as defined in Section 5.1 <xref target="RFC9110"/></t>
      </li>
      <li>
        <t>Mandatory-to-Specify: No. If not specified, the default behavior is not to add the header in the response.</t>
      </li>
    </ul>
    <t>Property: allow-methods</t>
    <ul>
      <li>
        <t>Description: A list of request method tokens the dCDN will include in the Access-Control-Allow-Methods response header to a CORS preflight request.</t>
      </li>
      <li>
        <t>Type: Array of method tokens as defined in Section 9.1 <xref target="RFC9110"/></t>
      </li>
      <li>
        <t>Mandatory-to-Specify: No. If not specified, the default behavior is not to add the header in the response.</t>
      </li>
    </ul>
    <t>Property: allow-headers</t>
    <ul>
      <li>
        <t>Description: A list of header names the dCDN will include in the Access-Control-Allow-Headers response header to a CORS preflight request.</t>
      </li>
      <li>
        <t>Type: Array of Field Names as defined in Section 5.1 <xref target="RFC9110"/></t>
      </li>
      <li>
        <t>Mandatory-to-Specify: No. If not specified, the default behavior is not to add the header in the response.</t>
      </li>
    </ul>
    <t>Property: allow-credentials</t>
    <ul>
      <li>
        <t>Description: The value the dCDN will include in the Access-Control-Allow-Credentials response header to a CORS preflight request.</t>
      </li>
      <li>
        <t>Type: Boolean</t>
      </li>
      <li>
        <t>Mandatory-to-Specify: No. If not specified, the default behavior is not to add the header in the response.</t>
      </li>
    </ul>
    <t>Property: max-age</t>
    <ul>
      <li>
        <t>Description: The value the dCDN will include in the Access-Control-Max-Age response header to a CORS preflight request.</t>
      </li>
      <li>
        <t>Type: Integer</t>
      </li>
      <li>
        <t>Mandatory-to-Specify: No. If not specified, the default behavior is not to add the header in the response.</t>
      </li>
    </ul>
    <t>Property: no-origin-response-headers</t>
    <ul>
      <li>
        <t>Description: In the case of a request that has no Origin field, return this set of headers with the response. Content providers need to deal with devices or applications that, even not sending the Origin header in the request, are expecting to receive the Access-Control-* headers in the response.</t>
      </li>
      <li>
        <t>Type: Array of MI.AccessControlHeaders objects.</t>
      </li>
      <li>
        <t>Mandatory-to-Specify: No. If not specified, the default behavior is not to add any CORS response headers.</t>
      </li>
    </ul>
    <t>Property: preflight-only</t>
    <ul>
      <li>
        <t>Description: If this flag is set to "true" the dCDN will only generate synthetic responses to OPTIONS requests with proper CORS response headers.</t>
      </li>
      <li>
        <t>Type: Boolean</t>
      </li>
      <li>
        <t>Mandatory-to-Specify: No. The default is "false", so CORS response headers logic will be injected for all HTTP methods.</t>
      </li>
    </ul>
    <section anchor="h.4bkljf3s2m4a">
      <name>MI.AccessControlAllowOrigin</name>
      <t>The MI.AccessControlAllowOrigin object has the following properties:</t>
      <t>Property: allow-list</t>
      <ul>
        <li>
          <t>Description: List of valid expressions that will be used to match the request Origin header. The Origin header is an HTTP extension. Its value is a variation of the Referer header that does not reveal a path in some specific requests and is used for cross-origin requests.  Permitted values for the Origin header are of the form schema://host[:port] as defined in Sections 3.1, 3.2.2, and 3.2.3 of <xref target="RFC3986"/></t>
        </li>
        <li>
          <t>Type: Array of Strings, where each String is a pattern as defined in Section 4.1.5 <xref target="RFC8006"/></t>
        </li>
        <li>
          <t>Mandatory-to-Specify: Yes</t>
        </li>
      </ul>
      <t>Property: wildcard-return</t>
      <ul>
        <li>
          <t>Description: If set to "true", the dCDN will include a wildcard (*) in the Access-Control-Allow-Origin response header. If "false", the dCDN MUST reflect the value of the Origin request header in the Access-Control-Allow-Origin response header.</t>
        </li>
        <li>
          <t>Type: Boolean</t>
        </li>
        <li>
          <t>Mandatory-to-Specify: Yes</t>
        </li>
      </ul>
    </section>
    <section anchor="h.dain2lshar0y">
      <name>MI.AccessControlHeaders</name>
      <t>The MI.AccessControlAllowHeaders object has the following properties:</t>
      <t>Property: name</t>
      <ul>
        <li>
          <t>Description: The name of the HTTP header.</t>
        </li>
        <li>
          <t>Type: String</t>
        </li>
        <li>
          <t>Mandatory-to-Specify: Yes</t>
        </li>
      </ul>
      <t>Property: value</t>
      <ul>
        <li>
          <t>Description: The new value of the named HTTP header.</t>
        </li>
        <li>
          <t>Type: String. A static string.</t>
        </li>
        <li>
          <t>Mandatory-to-Specify: Yes</t>
        </li>
      </ul>
    </section>
  </section>
  <section anchor="h.lwyp7db0gbzb">
    <name>Examples </name>
    <t>The informative examples below demonstrate how to configure response headers dynamically for CORS validation.</t>
    <t>The following is an informative example of a CORS validation configuration that does not include CORS preflight requests:</t>
    <figure>
      <sourcecode><![CDATA[{
  "generic-metadata-type": "MI.CrossoriginPolicy",
  "generic-metadata-value": {
    "allow-origin": {
      "allow-list": [
        {
          "pattern": "https://sourcepage.example.com"
        }
      ],
      "wildcard-return": true
    }
  }
}]]></sourcecode>
    </figure>
    <t>The following is an informative example of configuration to the dCDN to generate synthetic responses to CORS requests and CORS preflight requests:</t>
    <figure>
      <sourcecode><![CDATA[{
  "generic-metadata-type": "MI.CrossoriginPolicy",
  "generic-metadata-value": {
    "allow-origin": {
      "allow-list": [
        {
          "pattern": "*://sourcepage.example.com"
        }
      ],
      "wildcard-return": false
    },
    "allow-methods": [ "GET", "POST" ],
    "allow-credentials": true,
    "allow-headers": [ "X-PINGOTHER", "Content-Type" ],
    "expose-headers": [ "X-User", "Authorization" ],
    "max-age": 3600,
    "no-origin-response-headers": [
        {
          "name": "Access-Control-Allow-Origin",
          "value": "https://sourcepage.example.com"
        }
      ],
    "preflight-only": false
  }
}]]></sourcecode>
    </figure>
  </section>
</section><section anchor="h.vr4qe3ob12bs">
  <name>MI.AllowCompress</name>
  <t>Downstream CDNs often have the ability to compress HTTP response bodies in cases where the client has declared that it can accept compressed responses (via an Accept-Encoding header), but the source/origin has returned an uncompressed response.</t>
  <t>The specific compression algorithm used by the dCDN is negotiated by the client's Accept-Encoding header according to Section 12.5.3 <xref target="RFC9110"/> (including "q=" preferences) and the compression capabilities available on the dCDN. </t>
  <t>In addition, HeaderTransform allows the uCDN to normalize, or modify, the Accept-Encoding header to allow for fine-grain control over the selection of the compression algorithm (e.g., gzip, compress, deflate, br, etc.).</t>
  <t>MI.AllowCompress is a new GenericMetadata object that allows the dCDN to compress content before sending it to the client.</t>
  <t>Property: allow-compress</t>
  <ul>
    <li>
      <t>Description: If set to "true", the dCDN SHOULD try to compress the response to the client based on the Accept-Encoding request header and its available capabilities. In case is not able to do the compression, the content will be delivered uncompressed.</t>
    </li>
    <li>
      <t>Type: Boolean</t>
    </li>
    <li>
      <t>Mandatory-to-Specify: No. The default is "false".</t>
    </li>
  </ul>
  <section anchor="h.abw326fc982x">
    <name>Examples </name>
    <t>The following is an informative example of the usage of MI.AllowCompress:</t>
    <figure>
      <sourcecode><![CDATA[{
    "generic-metadata-type": "MI.AllowCompress",
    "generic-metadata-value": {
        "allow-compress": true
    }
}]]></sourcecode>
    </figure>
  </section>
</section><section anchor="h.29x3h84fw9yb">
  <name>MI.ClientConnectionControl</name>
  <t>Configuration metadata is required to define how connections to a client are maintained by a dCDN. In some use cases, like video streaming or other critical object delivery, UA applications' connection to the cache server must be managed to ensure the best possible user experience. This metadata allows a uCDN to accommodate device-specific constraints and performance optimization. A dCDN can also benefit from this configuration metadata to meet its security and resource consumption requirements.</t>
  <t>MI.ClientConnectionControl is a new GenericMetadata object that specifies how the uCDN wants that the dCDN manages its connections to UAs. </t>
  <t>Property: connection-keep-alive-time-ms</t>
  <ul>
    <li>
      <t>Description: Specifies the time, in milliseconds, to keep an idle connection open before trying to close it.</t>
    </li>
    <li>
      <t>Type: Integer</t>
    </li>
    <li>
      <t>Mandatory-to-Specify: No. When not specified, a default value selected by the dCDN will be used.</t>
    </li>
  </ul>
  <section anchor="h.pi88fxh7pe33">
    <name>Examples </name>
    <t>The following informative example shows how a connection setup and a keep alive timeout of 3 seconds can be set for client connections to a dCDN:</t>
    <figure>
      <sourcecode><![CDATA[  {
    "generic-metadata-type": "MI.ClientConnectionControl",
    "generic-metadata-value": {
      "connection-keep-alive-time-ms": 3000
    }
  }]]></sourcecode>
    </figure>
  </section>
</section><section anchor="Security" title="Security Considerations">
            <t>
            The FCI and MI objects defined in this document are transferred via the interfaces defined in CDNI <xref target="RFC8006"/> which describes how to secure these interfaces by protecting integrity and confidentiality while ensuring the authenticity of the dCDN and uCDN.
            </t>
        </section><section anchor="IANA" title="IANA Considerations">
    <section anchor="IANA.cdni.payload.types" title="CDNI Payload Types">
        <t>This document requests the registration of the following entries under the "CDNI Payload Types" registry hosted by IANA:
        </t>
        <table>
            <name>CDNI Payload Types</name>
            <thead>
                <tr><td>Payload Type</td><td>Specification</td></tr>
            </thead>
            <tbody>
                <tr><td>MI.CrossoriginPolicy</td><td>RFCthis</td></tr>
                <tr><td>MI.AccessControlAllowOrigin</td><td>RFCthis</td></tr>
                <tr><td>MI.AllowCompress</td><td>RFCthis</td></tr>
                <tr><td>MI.ClientConnectionControl</td><td>RFCthis</td></tr>
                <tr><td>MI.AccessControlHeaders</td><td>RFCthis</td></tr>
            </tbody>
            </table>
            <t>
            [RFC Editor: Please replace RFCthis with the published RFC number for
            this document.]
        </t>  
        <section anchor="IANA.cdni.payload.types.CrossOriginPolicy" title="CDNI MI CrossoriginPolicy Payload Type">
            <t>Purpose: The purpose of this Payload Type is to distinguish CrossoriginPolicy MI objects (and any associated capability advertisement)</t>
            <t>Interface: MI/FCI</t>
            <t>Encoding: See <xref target="h.e1lhw0cdqlzq"/></t>
        </section>
        <section anchor="IANA.cdni.payload.types.AccessControlAllowOrigin" title="CDNI MI AccessControlAllowOrigin Payload Type">
            <t>Purpose: The purpose of this Payload Type is to distinguish AccessControlAllowOrigin MI objects (and any associated capability advertisement)</t>
            <t>Interface: MI/FCI</t>
            <t>Encoding: See <xref target="h.4bkljf3s2m4a"/></t>
        </section>
        <section anchor="IANA.cdni.payload.types.AllowCompress" title="CDNI MI AllowCompress Payload Type">
            <t>Purpose: The purpose of this Payload Type is to distinguish AllowCompress MI objects (and any associated capability advertisement) </t>
            <t>Interface: MI/FCI</t>
            <t>Encoding: See <xref target="h.vr4qe3ob12bs"/></t>
        </section>
        <section anchor="IANA.cdni.payload.types.ClientConnectionControl" title="CDNI MI ClientConnectionControl Payload Type">
            <t>Purpose: The purpose of this Payload Type is to distinguish ClientConnectionControl MI objects (and any associated capability advertisement) </t>
            <t>Interface: MI/FCI</t>
            <t>Encoding: See <xref target="h.29x3h84fw9yb"/></t>
        </section>

        <section anchor="IANA.cdni.payload.types.AccessControlHeaders" title="CDNI MI AccessControlHeaders Payload Type">
            <t>Purpose: The purpose of this Payload Type is to distinguish AccessControlHeaders MI objects (and any associated capability advertisement) </t>
            <t>Interface: MI/FCI</t>
            <t>Encoding: See <xref target="h.dain2lshar0y"/></t>
        </section>

    </section>
</section><section anchor="Acknowledgements" title="Acknowledgements">
            <t>
                The authors would like to express their gratitude to the members of the Streaming Video Technology Alliance <xref target="SVTA"/> Open Caching Working Group for their contributions and guidance.
            </t>
            <t>Particularly the following people contribute in vairous ways to the content of this draft:</t>
                <ul>
                    <li>Guillaume Bichot (Broadpeak)</li>
                    <li>Christoph Neumann (Broadpeak)</li>
                    <li>Chris Lemmons (Comcast)</li>
                    <li>Pankaj Chaudhari (Disney Streaming)</li>
                    <li>Robert Colantuoni (Disney Streaming)</li>
                    <li>Will Power (Lumen)</li>
                    <li>Rajeev RK (picoNETS)</li>
                    <li>Shmuel Asafi (Qwilt)</li>
                    <li>Yoav Gressel (Qwilt)</li>
                    <li>Nir Sopher (Qwilt)</li>
                    <li>Arnon Warshavsky (Qwilt)</li>
                    <li>Eric Klein (Sirius XM)</li>
                    <li>Francisco Cano Hila (Telefonica)</li>
                    <li>Ben Rosenblum (Vecima)</li>
                </ul>
        </section>
   </middle>
   <back>
      <references title="Normative References">
         <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
         <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.3986.xml"/>
         <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8006.xml"/>
         <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9110.xml"/>

      </references>
      <references title="Informative References">
         <reference anchor="SVTA" target="https://www.svta.org">
            <front>
               <title>Streaming Video Technology Alliance Home Page</title>
               <author><organization>SVTA</organization></author>
               <date />
            </front>
         </reference>

         <reference anchor="WHATWG-FETCH" target="https://fetch.spec.whatwg.org">
            <front>
               <title>Fetch Standard</title>
               <author><organization>Web Hypertext Application Technology Working Group (WHATWG)</organization></author>
               <date />
            </front>
         </reference> 
         <reference anchor="OC" target="https://opencaching.svta.org/">
            <front>
               <title>Open Caching: Interoperable Caching Specifications by the SVTA</title>
               <author><organization>SVTA</organization></author>
               <date />
            </front>
         </reference>
        
      </references>
   </back>
</rfc>
