From 8dd6680d38943c8cfb5a9c1eac03bca085aed9fe Mon Sep 17 00:00:00 2001 From: EarthlingDavey <15802017+EarthlingDavey@users.noreply.github.com> Date: Fri, 6 Dec 2024 13:09:47 +0000 Subject: [PATCH] Fix CF cookie dateLessThan and add IP condition. (#32) --- conf/node/controllers/cloudfront.js | 7 +++++-- conf/node/controllers/cloudfront.test.js | 15 +++++++++++++++ conf/node/server.js | 3 +++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/conf/node/controllers/cloudfront.js b/conf/node/controllers/cloudfront.js index 51d0b5e..bc4ffd5 100644 --- a/conf/node/controllers/cloudfront.js +++ b/conf/node/controllers/cloudfront.js @@ -105,7 +105,7 @@ export const getDateLessThan = () => { * @returns {import('@aws-sdk/cloudfront-signer').CloudfrontSignedCookiesOutput} cookies - The signed CloudFront cookies */ -export const getCookies = ({ resource, dateLessThan }) => { +export const getCookies = ({ resource, dateLessThan, ipAddress }) => { // Check if the cache has a value for the resource const cachedValue = cache.cookieSets?.[resource]?.dateLessThan === dateLessThan; @@ -121,7 +121,10 @@ export const getCookies = ({ resource, dateLessThan }) => { Resource: resource, Condition: { DateLessThan: { - "AWS:EpochTime": new Date(dateLessThan).getTime() / 1000, // time in seconds + "AWS:EpochTime": dateLessThan, // time in seconds + }, + IpAddress: { + "AWS:SourceIp": ipAddress, }, }, }, diff --git a/conf/node/controllers/cloudfront.test.js b/conf/node/controllers/cloudfront.test.js index 24a42aa..4aff48e 100644 --- a/conf/node/controllers/cloudfront.test.js +++ b/conf/node/controllers/cloudfront.test.js @@ -37,15 +37,30 @@ describe("getCookies", () => { it("should return cookies for CloudFront", () => { const dateLessThan = getDateLessThan(); const resource = "https://archive.example.com/*"; + const ipAddress = "127.0.0.1"; const result = getCookies({ resource, dateLessThan, + ipAddress, }); expect(result).toBeDefined(); expect(result["CloudFront-Key-Pair-Id"]).toBeDefined(); expect(result["CloudFront-Policy"]).toBeDefined(); expect(result["CloudFront-Signature"]).toBeDefined(); + + // Trim trailing underscores from result["CloudFront-Policy"] + const policyBase64 = result["CloudFront-Policy"].replace(/_*$/g, ""); + + const policy = JSON.parse(Buffer.from(policyBase64, "base64").toString()); + + const statement = policy.Statement[0]; + + expect(statement.Resource).toBe(resource); + expect(statement.Condition.DateLessThan["AWS:EpochTime"]).toBe( + dateLessThan, + ); + expect(statement.Condition.IpAddress["AWS:SourceIp"]).toBe(ipAddress); }); }); diff --git a/conf/node/server.js b/conf/node/server.js index 4dc3785..d898e97 100644 --- a/conf/node/server.js +++ b/conf/node/server.js @@ -76,6 +76,8 @@ app.post("/spider", function (req, res) { app.get("/access-archive", async function (req, res, next) { try { + const clientIp = req.headers["x-forwarded-for"] || req.ip; + // Get the current domain from the request const appUrl = new URL( `${req.headers["x-forwarded-proto"] || req.protocol}://${ @@ -90,6 +92,7 @@ app.get("/access-archive", async function (req, res, next) { const cookies = getCookies({ resource: `${cdnUrl.origin}/*`, dateLessThan: getDateLessThan(), + clientIp, }); // Set the cookies on the response