Skip to content

Instantly share code, notes, and snippets.

@AlainODea
Last active March 1, 2018 13:56
Show Gist options
  • Save AlainODea/fa4a508414ce8c4c7c658ea29a7b791a to your computer and use it in GitHub Desktop.
Save AlainODea/fa4a508414ce8c4c7c658ea29a7b791a to your computer and use it in GitHub Desktop.
Akamai request signing using HMAC solution

Akamai Request signing using HMAC

Akamai Dynamic Site Delivery supports the use of variables and operations in its configurations that allows for a great deal more flexibility than you might imagine. A great example of this is introducing a form of request signing to make up for the lack of mutual TLS between the CDN and the origin servers.

Customer-configuration variables:

  • HMAC_IV_HEADER: name of the header that will be sent with the HMAC initiatlization vector
  • REQUEST_HMAC_HEADER: name of the header that will be sent with the request HMAC
  • CLIENT_SPKI_HEADER: name of the header that will be sent with the client certificate SPKI fingerprint
  • HMAC_SECRET: secret value to generate request HMAC that Origins must know to validate it
    • RECOMMENDATION: put this in SSM Parameter Store to secure it against disclosure

Internal state variables:

  • HMAC_IV: variable to be set via Generate - Random - Base 64 Encode
  • CLIENT_SPKI: variable to be set via Extract - Client Certificate - Hashed Fingerprint
  • HOST: variable to be set via Extract- Request Header - Host
  • USER_AGENT: variable to be set via Extract- Request Header - User-Agent
  • REQUEST_HMAC: variable to be set via Expression
    • Expression: {{user.PMUSER_HMAC_IV}}{{user.PMUSER_CLIENT_SPKI}}{{user.PMUSER_HOST}}{{user.PMUSER_USER_AGENT}}
    • Operation: HMAC
    • HMAC Key: HMAC_SECRET
    • Algorithm: SHA256
<match:request.type value="CLIENT_REQ" result="true">
<assign:variable>
<name>PM_8</name>
<value>t</value>
<hidden>on</hidden>
</assign:variable>
</match:request.type>
<match:variable name="PM_8" value="t" result="true">
<comment:note value="Start Feature setVariable"/>
<assign:variable>
<name>PMUSER_HMAC_IV</name>
<hidden>off</hidden>
<sensitive>off</sensitive>
<transform>
<rand>
<min>0</min>
<max>4294967295</max>
</rand>
<base64Encode/>
</transform>
</assign:variable>
<comment:note value="End Feature setVariable"/>
<comment:note value="Start Feature setVariable"/>
<assign:extract-value>
<location>Client_Certificate</location>
<location-id>fingerprint_dyn</location-id>
<location-id-prefix-match>off</location-id-prefix-match>
<variable-name>PMUSER_CLIENT_SPKI</variable-name>
<hidden>off</hidden>
<sensitive>off</sensitive>
</assign:extract-value>
<comment:note value="End Feature setVariable"/>
<comment:note value="Start Feature setVariable"/>
<assign:extract-value>
<location>Client_Request_Header</location>
<location-id>Host</location-id>
<location-id-prefix-match>off</location-id-prefix-match>
<variable-name>PMUSER_HOST</variable-name>
<hidden>off</hidden>
<sensitive>off</sensitive>
</assign:extract-value>
<comment:note value="End Feature setVariable"/>
<comment:note value="Start Feature setVariable"/>
<assign:extract-value>
<location>Client_Request_Header</location>
<location-id>User-Agent</location-id>
<location-id-prefix-match>off</location-id-prefix-match>
<variable-name>PMUSER_USER_AGENT</variable-name>
<hidden>off</hidden>
<sensitive>off</sensitive>
</assign:extract-value>
<comment:note value="End Feature setVariable"/>
<comment:note value="Start Feature setVariable"/>
<assign:variable>
<name>PMUSER_REQUEST_HMAC</name>
<value>%(PMUSER_HMAC_IV)%(PMUSER_CLIENT_SPKI)%(PMUSER_HOST)%(PMUSER_USER_AGENT)</value>
<hidden>off</hidden>
<sensitive>off</sensitive>
<transform>
<hmac>
<key>%(PMUSER_HMAC_SECRET)</key>
<algorithm>SHA256</algorithm>
</hmac>
</transform>
</assign:variable>
<comment:note value="End Feature setVariable"/>
<comment:note value="Start Feature modifyOutgoingRequestHeader"/>
<edgeservices:modify-outgoing-request.remove-header name="AKA_PM_%(PMUSER_HMAC_IV_HEADER)">
<name>%(PMUSER_HMAC_IV_HEADER)</name>
<status>on</status>
</edgeservices:modify-outgoing-request.remove-header>
<edgeservices:modify-outgoing-request.add-header name="AKA_PM_%(PMUSER_HMAC_IV_HEADER)">
<name>%(PMUSER_HMAC_IV_HEADER)</name>
<value>%(PMUSER_HMAC_IV)</value>
<status>on</status>
</edgeservices:modify-outgoing-request.add-header>
<comment:note value="End Feature modifyOutgoingRequestHeader"/>
<comment:note value="Start Feature modifyOutgoingRequestHeader"/>
<edgeservices:modify-outgoing-request.remove-header name="AKA_PM_%(PMUSER_CLIENT_SPKI_HEADER)">
<name>%(PMUSER_CLIENT_SPKI_HEADER)</name>
<status>on</status>
</edgeservices:modify-outgoing-request.remove-header>
<edgeservices:modify-outgoing-request.add-header name="AKA_PM_%(PMUSER_CLIENT_SPKI_HEADER)">
<name>%(PMUSER_CLIENT_SPKI_HEADER)</name>
<value>%(PMUSER_CLIENT_SPKI)</value>
<status>on</status>
</edgeservices:modify-outgoing-request.add-header>
<comment:note value="End Feature modifyOutgoingRequestHeader"/>
<comment:note value="Start Feature modifyOutgoingRequestHeader"/>
<edgeservices:modify-outgoing-request.remove-header name="AKA_PM_%(PMUSER_REQUEST_HMAC_HEADER)">
<name>%(PMUSER_REQUEST_HMAC_HEADER)</name>
<status>on</status>
</edgeservices:modify-outgoing-request.remove-header>
<edgeservices:modify-outgoing-request.add-header name="AKA_PM_%(PMUSER_REQUEST_HMAC_HEADER)">
<name>%(PMUSER_REQUEST_HMAC_HEADER)</name>
<value>%(PMUSER_REQUEST_HMAC)</value>
<status>on</status>
</edgeservices:modify-outgoing-request.add-header>
<comment:note value="End Feature modifyOutgoingRequestHeader"/>
</match:variable>
@thisismana
Copy link

Sorry for this silly question, but where does this XML-Snippet actually go? Does this require a certain add-on to be purchased from Akamai ("Akamai Advanced $cripting Upgrade ©™")?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment